LogoLogo
Go to SiliconJoin Telegram 💬
  • About
    • Silicon Overview
      • Features
      • Missions
    • Silicon identity protocol
  • Users
    • Wallet configuration
    • Bridge
      • Deposit to Silicon
      • Withdrawal from Silicon
    • Block explorer
    • Fees
  • Builders
    • Build on Silicon
    • Build on OpenCohort & NamedWallet
      • Contract
        • OpenNameTag
        • Account Abstraction
      • Framework
        • Merkle Tree & Merkle Proof
        • Participants
        • Components Overview
        • Address & Identity
        • Use Case
        • Developer
          • Cohort
          • Protocol
            • Base API
            • Manage API
            • Prover API
          • Airdrop
            • Reward Type
          • Play OpenCohort
          • Named Wallet
        • Public Prover Lists
    • Network information
    • zkEVM contracts
    • Testnet
      • Setup
      • Faucet
      • Bridge
      • Block Explorer
      • zkEVM Testnet Contracts
  • Support
    • Contact Silicon
    • Silicon quick guide
  • More
    • Brand
    • Security
    • Terms of use
    • Privacy Policy
    • Open Source License
  • External Links
    • Polygon CDK
    • Polygon zkEVM
  • Agglayer
Powered by GitBook
LogoLogo

Sites

  • Silicon
  • Scope
  • Bridge

Community

  • X
  • Medium
  • Telegram

Developers

  • Testnet Scope
  • Testnet Bridge

Copyright Silicon(Highdraw). All Rights Reserved.

On this page
  • Add Members to a Cohort
  • Removing Members from a Cohort:
  • Adding or Removing Identity Mapping in a Cohort
  • Preparing a Cohort Snapshot
  • Confirmation of Cohort Snapshot

Was this helpful?

  1. Builders
  2. Build on OpenCohort & NamedWallet
  3. Framework
  4. Developer
  5. Protocol

Manage API

If a Manager API’s role is solely focused on managing the cohort's foundational information, membership, and identity to provide snapshot rollup data to the Prover, it does not strictly need to follow the Protocol outlined on this page. Manager APIs may adopt more flexible permission structures, alternative verification methods, or even entirely different protocols depending on the provider. The descriptions below refer to the default Manager API as implemented by the Silicon development team.

  • Required Permissions: Owner of the Cohort NFT item on the Silicon Network.

  • Permission Verification: An HTTP header authorization containing the signature from the Cohort Item owner on keccak256(request.body), valid within N seconds from the timestamp (N = 30 seconds).

Add Members to a Cohort

POST /cohort/{cohortId}/member/add

  • Adds an address to a specific cohort. If the address is already included, only its Weight is updated.

// request
{
  "validUntil": 1718266039,
  "members":{
    "0x0000000000000000000000000000000000000400":1,
    "0x0000000000000000000000000000000000000500":2
  },
  "signature": "0xabcsafbasdb..."
}

// response
{
  "statusCode": 200,
  "data": affectedRowCount
}

Removing Members from a Cohort:

POST /cohort/{cohortId}/member/remove

  • Removes a specified address from a cohort. If the address does not exist in the cohort, the action is ignored.

// request
{
  "validUntil": 1718266039,
  "members":[
    "0x0000000000000000000000000000000000000400", 
    "0x0000000000000000000000000000000000000500"
  ],
  "signature": "0xabiofsdnboiqnw..."
}

// response
{
  "statusCode": 200,
  "data": affectedRowCount
}

POST /cohort/{cohortId}/member/remove/all

  • Removes all members from a cohort. If the address does not exist in the cohort, the action is ignored.

// request
{
  "validUntil": 1718266039,
  "signature": "0xabiofsdnboiqnw..."
}

// response
{
  "statusCode": 200
  "data": affectedRowCount
}

Adding or Removing Identity Mapping in a Cohort

POST /identity/update

  • Maps an actual EOA to an address (Identity) within a specified cohort and submits a signature for the mapping.

  • This function operates independently of the snapshot preparation status.

  • Updating signatures for addresses not currently in the cohort is also supported.

  • If a new signature is received and is valid, it will overwrite any previous signature (e.g., EOA change).

  • To delete a signature, set the EOA to the 0x0 address and submit a signed message. However, to prevent the reuse of a previous signature, it’s recommended to process it as a revocation.3

signature

The signature is signed as follows. This signature is used by the AirdropContract, which verifies it through the code below when collecting an ExtraSignature for airdrop targeting this cohort.

  • Silicon Chain Cohort NFT Verification Code

//import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
//import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";

bytes32 hash = keccak256(abi.encode(address(cohortNFTAddress), getChainId(), identityEOA, addressEOA); 
bytes32 signingHash = MessageHashUtils.toEthSignedMessageHash(hash);
require(cohortOwner == ECDSA.recover(signingHash, signature));
  • Each identity signature example

const { defaultAbiCoder, keccak256 } = require('ethers/lib/utils');

(async() => {
    const cohortNFTAddress = "0x0000000000000000000000000000000000001234";
    const chainId = "1414";
    const uniqueKey = "0x000000000000000000000000000000000000dead";
    const target = "0x7777777777777777777777777777777777777777";

    const dataBytes = defaultAbiCoder.encode(
        ['string', 'address', 'uint256', 'address', 'address'],
        ['OpenCohort:Identity', cohortNFTAddress, chainId, uniqueKey, target]
    );
    console.log(`Data Bytes: ${dataBytes}\\n`);

    const dataHash = keccak256(dataBytes);
    console.log(`Data Hash: ${dataHash}\\n`);

    const signingBytes = Buffer.concat([
        Buffer.from('\\x19Ethereum Signed Message:\\n32', 'ascii'),
        Buffer.from(dataHash.replace("0x",""), 'hex')
    ])
    const signingHash = keccak256(signingBytes);
    console.log(`Signing Hash: ${signingHash}`);
})()

Request & Response

// request
{
  "validUntil": 1718266039,
  "signer":"0x12345..Address" // the address that signed the identity map below
  //"timestamp", "owner" etc. can be included but will be ignored if present 
  "identities":{
    // member address included in Cohort: [actual mapped EOA address, signature by Cohort Owner for mapping]
    "0x0000000000000000000000000000000000000400":["0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0xSIGNATURE_R_S_V"], // V= 0x1b or 0x1c
    "0x0000000000000000000000000000000000000500":["0xAddress","0xSIGNATURE_R_S_V"]
  },
  
  "signature": "0xaoidsghngoiqwng..."
}

// fail response
{
  "statusCode":500,

  // Request method check
  "message":"invalid_identity",  // if the identity item is missing or not in the Dict<EOA, [EOA, SIG]> format
  "message":"invalid_signature", // if the SIGNATURE provided for any identity item is invalid or not from the signer (in this case, no request processing occurs; validation is prioritized)
}

Preparing a Cohort Snapshot

POST /cohort/{cohortId}/snapshot/initialize

  • Confirms nonce 0 snapshot data for a Cohort with a specified Hash and generates a snapshot.

// request
{
  "validUntil": 1718266039,
  "signature": "0xabsabnoiqwengqwe..."
}

// response
// If the Merkle Root Hash generated from the addresses currently in the cohort matches the Merkle Root Hash set on-chain at nonce 0, it will immediately process the same actions as a snapshot submission.
{
  "statusCode":200,
  "message": "success"
}

// fail response
{
  "statusCode": error_code
  "message": error_message	
}

POST /cohort/{cohortId}/snapshot/prepare

  • Requests the necessary information to create a finalized snapshot of the addresses currently under management. This is only possible if the RootHash for the Cohort item is generated.

// request
{
  "validUntil": 1718266039,
  "snapshotTime": 1718266039,
  "signature": "0x1o2hnioadsngioqw..."
}

// response
{
  "statusCode": 200,
  "data": {
    "signatureInfo": {
      "address": "0x0000000000000000000000000000000000000700",
      "cohortId":{cohortId},
      "merkleRoot":"0xd0e15e9b115375b9725e57604121792e871db3128dc0c5683601d8288f755930",
      "timestamp":1718266039, // Snapshot reference time (for rollup, returned exactly as requested in the request).
      "prover":"<https://api-prover.silicon.network>",
      "totalWeight":10000000,
      "nonce":1, // The first snapshot begins at 1.
    },
    "expiredAt":1718266099 // Submit signatures within this time. 
  }
}

// fail response
{
  "successCod": error_code,
  "message": error_message	
}

Confirmation of Cohort Snapshot

POST /cohort/{cohortId}/snapshot/submit

  • Signatures for a pending snapshot are submitted via prepare, finalizing the snapshot data and storing the rollup data.

Signature

The signature is generated based on the signatureInfo provided in prepare, as shown below.

  • Reference: Silicon Network Cohort NFT verification code

//import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
//import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";

bytes32 hash = keccak256(abi.encode("OpenCohort:Rollup", address(cohortNFTAddress), getChainId(), CohortId, nonce, merkleRoot, totalWeight, totalCount, prover, timestamp)); // tokenId == CohortId
bytes32 signingHash = MessageHashUtils.toEthSignedMessageHash(hash);
require(cohortOwner == ECDSA.recover(signingHash, signature));
  • Example of a rollup signature

const { defaultAbiCoder, keccak256 } = require('ethers/lib/utils');

(async() => {
    const cohortNFTAddress = "0x0000000000000000000000000000000000001234";
    const chainId = "1414";
    const tokenId = "1234";
    const nonce = "1";
    const merkleRoot = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
    const totalWeight = "10000000000000000";
    const totalCount = "1000";
    const prover = "<https://prover.prover.prover>";
    const timestamp = "777777777";

    //bytes32 hash = keccak256(abi.encode(address(this), getChainId(), tokenId, nonce, merkleRoot, totalWeight, totalCount, prover, timestamp));
    const dataBytes = defaultAbiCoder.encode(
        ['string', 'address', 'uint256', 'uint256', 'uint256', 'bytes32', 'uint256',  'uint256', 'string', 'uint256'],
        ['OpenCohort:Rollup', cohortNFTAddress, chainId, cohortId, nonce, merkleRoot, totalWeight, totalCount, prover, timestamp]
    );
    console.log(`Data Bytes: ${dataBytes}\\n`);

    const dataHash = keccak256(dataBytes);
    console.log(`Data Hash: ${dataHash}\\n`);

    const signingBytes = Buffer.concat([
        Buffer.from('\\x19Ethereum Signed Message:\\n32', 'ascii'),
        Buffer.from(dataHash.replace("0x",""), 'hex')
    ])
    const signingHash = keccak256(signingBytes);
    console.log(`Signing Hash: ${signingHash}`);
})()

Request & Response

// request
{
  "validUntil": 1718266039,
  "snapshotTime": 1718266039,
  "snapshotSignature": "0xasdghioegqoeipwmngoiadsjmg",
  "signature":"0x99502d2cd9ea810a6a70f16374466fc45795d2c06f74e48....be8d1982ab130f9c257c73a1955479de6aeacd132133d3f861b"
}

// response
{
  "statusCode":200,
  "message": "success"
}

// fail response
{
  "successCod": error_code,
  "message": error_message	
}

PreviousBase APINextProver API

Last updated 2 months ago

Was this helpful?