{"id":20817488,"url":"https://github.com/chaintope/tapyrus-signer","last_synced_at":"2025-05-07T13:45:53.627Z","repository":{"id":37982486,"uuid":"221616973","full_name":"chaintope/tapyrus-signer","owner":"chaintope","description":"Tapyrus Signer reference implementation.","archived":false,"fork":false,"pushed_at":"2025-01-07T08:58:04.000Z","size":933,"stargazers_count":7,"open_issues_count":19,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-31T10:42:26.722Z","etag":null,"topics":["tapyrus"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chaintope.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-14T05:13:15.000Z","updated_at":"2025-01-07T08:58:08.000Z","dependencies_parsed_at":"2024-11-17T21:42:26.914Z","dependency_job_id":"32986b6e-bcaf-41cf-87f0-9b21ef0a7278","html_url":"https://github.com/chaintope/tapyrus-signer","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaintope%2Ftapyrus-signer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaintope%2Ftapyrus-signer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaintope%2Ftapyrus-signer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaintope%2Ftapyrus-signer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chaintope","download_url":"https://codeload.github.com/chaintope/tapyrus-signer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252889856,"owners_count":21820264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["tapyrus"],"created_at":"2024-11-17T21:42:18.886Z","updated_at":"2025-05-07T13:45:53.593Z","avatar_url":"https://github.com/chaintope.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tapyrus Signer Node [![Build Status](https://github.com/chaintope/tapyrus-signer/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/chaintope/tapyrus-signer/actions/workflows/ci.yml) [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n\nTapyrus Signer Node is provide and deploy federation signer network.\n\n## Overview\n- Communicate each signer node, using redis Pub/Sub.\n- Using Tapyrus core for candidate block generation, broadcasting and so on.\n\n\n## Requirement\nBuilding `node` requires Rust following version.\n```\n$ rustc --version\nrustc 1.41.0 (5e1a79984 2020-01-27)\n```\nAnd [Tapyrus-core](https://github.com/chaintope/tapyrus-core/) of latest version for run node.\n\n## Building the Source\n\nPlease run bellow command:\n```\ncargo build --release\n```\n\n# Signer Network Specification\n\nDescribe about how the signer node communicate with other node.\n\n## SignerID and Signer Index\n\nEach signer nodes are identified by each public keys. And also each nodes\nhave index. The index is assigned by public keys dictionary order index.\nRound master which is describing follow section is decided accoding to\nSigner Index.\n\n## Threshold Signature Scheme\n\nTapyrus Signer Network(TSN)'s signing algorithm bases on \"Provably Secure Distributed Schnorr Signatures and a (t, n) Threshold Scheme for Implicit Certificates\"[^1].\nIf you want to understand what is going on in TSN, We recommend reading section 4 \"A (t, n) Threshold Signature Scheme\" in the paper before.\n\nTSN produces schnorr signatures which is described in [Tapyrus Schnorr Singature Specification](https://github.com/chaintope/tapyrus-core/blob/master/doc/tapyrus/schnorr_signature.md)\n\n\u003e [^1]: Stinson, D. R., \u0026 Strobl, R. (2001). Provably secure distributed schnorr signatures and a (T, n) threshold scheme for implicit certificates. In Lecture Notes in Computer Science (including subseries Lecture Notes in Artificial Intelligence and Lecture Notes in Bioinformatics) (Vol. 2119, pp. 417–434). Springer Verlag. https://doi.org/10.1007/3-540-47719-5_33\n\n### Verifiable Secret Sharing\n\nThe threshold signature scheme uses [Verifiable secret sharing(VSS)](https://en.wikipedia.org/wiki/Verifiable_secret_sharing) inside. And TSN uses [Feldman's scheme](https://en.wikipedia.org/wiki/Verifiable_secret_sharing#Feldman’s_scheme).\nThe word of VSS appears in this repository means this scheme and sort of data format for VSS scheme.\n\n## Overview of Tapyrus Signer Network(TSN) How it works\n\nAfter 5 seconds of idling, the block generation round will begin. Each round is divided into roles - one master and \nthe other members - with the aim of building consensus on the candidate blocks proposed by the master.\n\nIf the agreement among all the signers exceeds the threshold in the round, the block becomes legitimate and is \nbroadcast to the Tapyrus blockchain network. Then the next round begins, and block generation continues.\n\nThe following describes in detail the messages used to exchange between the signer nodes and the specific algorithms.\n\n## Message Types\n\nThe communication among each node is perform on passing Message which is\nbroadcasted on Redis pub/sub.\n\nAll messages has signer id field which is specify by signer public key.\n\n| Message Type      | Payload        | Description                                                  |\n| ----------------- | -------------- | ------------------------------------------------------------ |\n| candidateblock    | Block          | Round master broadcasts to signer network a candidate block. |\n| blockvss          | BlockVSS       | Send vss for random secret.                                  |\n| blockparticipants | Vec \u0026lt; PublicKey \u0026gt; | Round master notify `signature issuing protocol` is going to be executed with the signers who are represented in payload keys |\n| blocksig          | LocalSig       | Broadcast local sig.                                         |\n| completedblock    | Block          | Round master broadcasts completed block.                     |\n\n\nCaution: Tapyrus-signer is using redis for to relay messages among each node. The word `send` and `broadcast` in the \ndescriptions for each message type means logical specification not actual behavior. Actually each node always send \nmessages to redis-server and redis relays the messages on pub/sub functionality. When it says `broadcast`, it means a \nmessage will be sent to a pub/sub channel where subscribed by all nodes. In the other hand, when it says `send`, it \nmeans a message will be sent to a channel where subscribed by a specific node.\n\n### Structure of payload\n\nAll messages are formatted as JSON when it is sent.\n\n#### BlockVSS Structure\n\nBlockVSS has two VSS secrets. The first one is for positive and the other one is for negative.\nThe word `positive` means that the secret share is generated based on not negated ephemeral key and other one is based \non negated. \nWhy the BlockVSS need to have these two VSS is that k value (which is described in \n[Tapyrus schnorr signature specification](https://github.com/chaintope/tapyrus-core/blob/master/doc/tapyrus/schnorr_signature.md#signing-algorithm)) \nmust be chosen as y coordinate of R becomes quadratic residue. \n\n* `Blockvss[0]` Sighash from the candidate block.\n* `Blockvss[1]` Object of additional data for the positive VSS.\n     * `parameter` Object of secret sharing parameters\n          * `threshold` Integer value of threshold - 1.\n          * `share_count` Integer value of signer count. (And also it is the number which shares should be created.)\n     * `commitments` Array of commitment. A commitment is a point of secp256k1 curve. Which has x and y coordinates.\n* `Blockvss[2]` Secret share for *positive*. Hex formatted scalar value of secp256k1 curve.\n* `Blockvss[3]` Object of additional data for the negative VSS. The fields are same with positive VSS's one.\n* `Blockvss[4]` Secret share for *negative*. Hex formatted scalar value of secp256k1 curve..\n\n\n*Example*\n```json\n{\n  \"Blockvss\": [\n    \"d68e99f1135c6661f174f4bee7c9b94a1e7dbb0eb7609f0aea118340ffd05944\",\n    {\n      \"parameters\": {\n        \"threshold\": 1,\n        \"share_count\": 3\n      },\n      \"commitments\": [\n        {\n          \"x\": \"1fc491aef36b480160d71b099fe376e58fe0a915d0b382bb2c5daeb2f46665d2\",\n          \"y\": \"d4ec3f9d4e5a7494447c9f97476abdc475376311e49b7ce6000f9d0640c08fe9\"\n        },\n        {\n          \"x\": \"647d33c9bb32320e8b7476743577180021f36e95aa939a96896e7e5be89f08fe\",\n          \"y\": \"6a68092234664285e4fd244623c406d8feead1e44c1be2b7272f77c733c4ab48\"\n        }\n      ]\n    },\n    \"23a7185d3f2b402ff54168b880da783a7535e55cbc3ad657e5da2f2336cb349c\",\n    {\n      \"parameters\": {\n        \"threshold\": 1,\n        \"share_count\": 3\n      },\n      \"commitments\": [\n        {\n          \"x\": \"1fc491aef36b480160d71b099fe376e58fe0a915d0b382bb2c5daeb2f46665d2\",\n          \"y\": \"2b13c062b1a58b6bbb836068b895423b8ac89cee1b648319fff062f8bf3f6c46\"\n        },\n        {\n          \"x\": \"4247c04efc03c0c94bb129715d2b8d6128018e607936d9e3075bbb87f411043e\",\n          \"y\": \"fc8a579ca133a73ad27b0e9499b180c18fe51110beb8ebc90e18d12f2a490f4a\"\n        }\n      ]\n    },\n    \"972ad402adf631e5a52ffe14803a40b19c6f578678a57bc833364842cce9c68\"\n  ]\n}\n```\n\n\n### LocalSig Structure\n\n`BlockSig[0]` Sighash from the candidate block.\n`BlockSig[1]` Local signature from a single signer. Final signature will be constructed if count of local signatures met the threshold.\n`BlockSig[2]` e of [schnorr signature](https://github.com/chaintope/tapyrus-core/blob/master/doc/tapyrus/schnorr_signature.md#signing-algorithm)\n\n*example*\n```json\n{\n  \"Blocksig\": [\n    \"d68e99f1135c6661f174f4bee7c9b94a1e7dbb0eb7609f0aea118340ffd05944\",\n    \"218f1a47f87b48fa5ee77202fd14b15dbd04f8ef63834a56c1821f9b4ee842ed\",\n    \"e645628bb53b9902f89771863037e99448069014ab99860b26a3a710a5f746df\"\n  ]\n}\n```\n\n## Round\n\nSigner Network has round. Before start the round, a signer node is elected\nround-robin as round master. The master start new round. A round produce\none block if it is succeed.\n\nIn following section, it describe communication flow for each master\nand member node.\n\n### Sequence Diagram\n\nThis is sequence diagram for communication among tapyrus-signer nodes. \n\n[![sequence diagram](https://mermaid.ink/img/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG5BbGljZShNYXN0ZXIpIC0-PiBBbGljZShNYXN0ZXIpOiBzbGVlcCByb3VuZCBkdXJhdGlvblxuTm90ZSBsZWZ0IG9mIEFsaWNlKE1hc3Rlcik6IE1hc3RlciBicm9hZGNhc3Q8YnIvPiBhIGNhbmRpZGF0ZSBibG9ja1xuQWxpY2UoTWFzdGVyKSAtPj4gQm9iOiBjYW5kaWRhdGVibG9ja1xuQWxpY2UoTWFzdGVyKSAtPj4gQ2Fyb2w6IGNhbmRpZGF0ZWJsb2NrXG5cbk5vdGUgbGVmdCBvZiBBbGljZShNYXN0ZXIpOiBBbGwgc2lnbmVycyBzZW5kIHZzczxici8-IHRvIGVhY2ggb3RoZXIuXG5BbGljZShNYXN0ZXIpIC0-PiBCb2I6IGJsb2NrdnNzXG5BbGljZShNYXN0ZXIpIC0-PiBDYXJvbDogYmxvY2t2c3NcbkJvYiAtPj4gQWxpY2UoTWFzdGVyKTogYmxvY2t2c3NcbkJvYiAtPj4gQ2Fyb2w6IGJsb2NrdnNzXG5DYXJvbCAtPj4gQWxpY2UoTWFzdGVyKTogYmxvY2t2c3NcbkNhcm9sIC0-PiBCb2I6IGJsb2NrdnNzXG5cbk5vdGUgbGVmdCBvZiBBbGljZShNYXN0ZXIpOiBNYXN0ZXIgYnJvYWRjYXN0PGJyLz4gcGFydGljaXBhbnRzIGZvciB0aGU8YnIvPiBhZnRlciBmbG93Ljxici8-IEhlcmUgd2UgYXNzdW1lIHRoZSA8YnIvPnBhcnRpY2lwYW50cyBhcmUgQWxpY2U8YnIvPiBhbmQgQm9iLlxuQWxpY2UoTWFzdGVyKSAtPj4gQm9iOiBibG9ja3BhcnRpY2lwYW50c1xuQWxpY2UoTWFzdGVyKSAtPj4gQ2Fyb2w6IGJsb2NrcGFydGljaXBhbnRzXG5cbk5vdGUgbGVmdCBvZiBBbGljZShNYXN0ZXIpOiBFYWNoIHBhcnRpY2lwYW50PGJyLz4gYnJvYWRjYXN0IGJsb2Nrc2lnPGJyLz4gbWVzc2FnZS5cbkFsaWNlKE1hc3RlcikgLT4-IEJvYjogYmxvY2tzaWdcbkFsaWNlKE1hc3RlcikgLT4-IENhcm9sOiBibG9ja3NpZ1xuQm9iIC0-PiBBbGljZShNYXN0ZXIpOiBibG9ja3NpZ1xuQm9iIC0-PiBDYXJvbDogYmxvY2tzaWdcblxuTm90ZSBsZWZ0IG9mIEFsaWNlKE1hc3Rlcik6IE1hc3RlciByZWNvbnN0cnVjdDxici8-IGZpbmFsIHNpZ25hdHVyZSBhbmQ8YnIvPiBzdWJtaXQgdG8gdGhlIFRhcHlydXM8YnIvPiBuZXR3b3JrLjxici8-IFRoZW4sIGJyb2FkY2FzdDxici8-IGNvbXBsZXRlZGJsb2NrPGJyLz4gbWVzc2FnZS5cbkFsaWNlKE1hc3RlcikgLT4-IEJvYjogY29tcGxldGVkYmxvY2tcbkFsaWNlKE1hc3RlcikgLT4-IENhcm9sOiBjb21wbGV0ZWRibG9jayIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19)](https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG5BbGljZShNYXN0ZXIpIC0-PiBBbGljZShNYXN0ZXIpOiBzbGVlcCByb3VuZCBkdXJhdGlvblxuTm90ZSBsZWZ0IG9mIEFsaWNlKE1hc3Rlcik6IE1hc3RlciBicm9hZGNhc3Q8YnIvPiBhIGNhbmRpZGF0ZSBibG9ja1xuQWxpY2UoTWFzdGVyKSAtPj4gQm9iOiBjYW5kaWRhdGVibG9ja1xuQWxpY2UoTWFzdGVyKSAtPj4gQ2Fyb2w6IGNhbmRpZGF0ZWJsb2NrXG5cbk5vdGUgbGVmdCBvZiBBbGljZShNYXN0ZXIpOiBBbGwgc2lnbmVycyBzZW5kIHZzczxici8-IHRvIGVhY2ggb3RoZXIuXG5BbGljZShNYXN0ZXIpIC0-PiBCb2I6IGJsb2NrdnNzXG5BbGljZShNYXN0ZXIpIC0-PiBDYXJvbDogYmxvY2t2c3NcbkJvYiAtPj4gQWxpY2UoTWFzdGVyKTogYmxvY2t2c3NcbkJvYiAtPj4gQ2Fyb2w6IGJsb2NrdnNzXG5DYXJvbCAtPj4gQWxpY2UoTWFzdGVyKTogYmxvY2t2c3NcbkNhcm9sIC0-PiBCb2I6IGJsb2NrdnNzXG5cbk5vdGUgbGVmdCBvZiBBbGljZShNYXN0ZXIpOiBNYXN0ZXIgYnJvYWRjYXN0PGJyLz4gcGFydGljaXBhbnRzIGZvciB0aGU8YnIvPiBhZnRlciBmbG93Ljxici8-IEhlcmUgd2UgYXNzdW1lIHRoZSA8YnIvPnBhcnRpY2lwYW50cyBhcmUgQWxpY2U8YnIvPiBhbmQgQm9iLlxuQWxpY2UoTWFzdGVyKSAtPj4gQm9iOiBibG9ja3BhcnRpY2lwYW50c1xuQWxpY2UoTWFzdGVyKSAtPj4gQ2Fyb2w6IGJsb2NrcGFydGljaXBhbnRzXG5cbk5vdGUgbGVmdCBvZiBBbGljZShNYXN0ZXIpOiBFYWNoIHBhcnRpY2lwYW50PGJyLz4gYnJvYWRjYXN0IGJsb2Nrc2lnPGJyLz4gbWVzc2FnZS5cbkFsaWNlKE1hc3RlcikgLT4-IEJvYjogYmxvY2tzaWdcbkFsaWNlKE1hc3RlcikgLT4-IENhcm9sOiBibG9ja3NpZ1xuQm9iIC0-PiBBbGljZShNYXN0ZXIpOiBibG9ja3NpZ1xuQm9iIC0-PiBDYXJvbDogYmxvY2tzaWdcblxuTm90ZSBsZWZ0IG9mIEFsaWNlKE1hc3Rlcik6IE1hc3RlciByZWNvbnN0cnVjdDxici8-IGZpbmFsIHNpZ25hdHVyZSBhbmQ8YnIvPiBzdWJtaXQgdG8gdGhlIFRhcHlydXM8YnIvPiBuZXR3b3JrLjxici8-IFRoZW4sIGJyb2FkY2FzdDxici8-IGNvbXBsZXRlZGJsb2NrPGJyLz4gbWVzc2FnZS5cbkFsaWNlKE1hc3RlcikgLT4-IEJvYjogY29tcGxldGVkYmxvY2tcbkFsaWNlKE1hc3RlcikgLT4-IENhcm9sOiBjb21wbGV0ZWRibG9jayIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19)\n\n### Round Master Flow\n\n1. Start Next Round\n     * If the round-duration timer is not started\n           *  The node starts the timer for counting the round-duration\n     * If the round-duration timer is started\n           * If the timer is not up\n                * If the node receives candidateblock message\n                     * The node works as a Member node and leaves this flow.\n           * If the timer is up\n                * The node goes 2nd step.\n2. Produce a candidate block\n     * Call getnewblock\n          * In getnewblock RPC, it test block validity, so we no longer call testproposedblock RPC.\n     * Publish new block to all other signers via Redis pub/sub\n3. Signature issuing protocol\n     * This step has no differences with member process. So describe below.     \n4. Submit Block\n     * Set signature created in 3.Signature issuing protocol into block header.\n     * Call submitblock RPC\n     * Publish completed block with completedblock message.\n5. Decide Next Master\n     * Decide next master node according to signer's public keys dictionary order.\n     * Start next round as member.\n\n### Round Member Flow\n\n1. Start Next Round\n     * Wait for candidateblock message.\n2. Check candidate block\n     * If the node receives candidateblock message, start to progress.\n     * Call testproposedblock RPC\n     * If the block is NG, logs warning.\n     * If the block is OK, go next step.\n3. Signature issuing protocol\n     * This step has no differences with member process. So describe below.\n4. Waiting completed block\n     * Wait for completedblock message. If got, go next step.\n5. Decide Next Master\n     * When receive completedblock message, decide next master node same way as master flow.\n     * Start next round as decided role.\n\n### Signature issuing protocol\n\n1. Sharing VSSs\n     * Generate random secret e_i.\n     * Calculate own commitments from random polynomial and own secret e_i. \n     * Calculate VSSs for all signers each from random polynomial and each signer index.\n     * Send commitments and VSSs to each signer using `blockvss` message. Especially, master signer should pay attention for each VSS must be sent to correct signer.\n     * Receive VSSs from other signers and verify it using commitments.\n     * If you are Master node, the number of VSSs met number of threshold, go next step.\n     * If you are Member node, just wait `blockparticipants` message.\n2. Master node declares signers list who can participate after steps\n     *  If you are Master node, then broadcast blockparticipants message which represents who can participate Sharing local signature step.\n     *  If you are Member node, do nothing. just wait `blockparticipants` message.\n3. Sharing local signatures\n     * This step must be done by only signers who was designated in `blockparticipants` message. And all participants must have all VSSs from all other participants.\n     * Calculate own share from VSSs got in \"Sharing VSSs\".\n     * Calculate temporary aggregated public key from commitments which correspond constant term's coefficients\n     * Generate local signature from below information.\n          * Two shares which are generated in Key Generation Protocol and previous step.\n          * Aggregated public key which is generated in Key Generation Protocol.\n          * Temporary aggregated public key which is created in previous step.\n          * Sighash which is message of signature. It is hash value of block header except proof field.\n     * Broadcast local signature using blocksig message.\n     * Receive local signatures from other nodes and verify them.\n     * If the number of local signatures met threshold, aggregate final signature and put it in block header .\n\n### About Timeout\n\nEach round need to finish in 65 secs, otherwise the round was fail and start\nnext round. This mechanism is for availability. Because of timeout, Signer\nNetwork can continue if some signer node stopped.\n\n65 secs is consisted of round duration and actually time limit for round process.\nRound duration can be set by `--duration` option. Default is 60 secs.\nTime limit is fixed as 5 secs.\n\n## Now is alpha version\n\nCurrent implementation is not stable. So it has some problems.\n\n### Multi masters in a round appear\n\nDepending on the starting timing some nodes, there are multi master nodes\nappear. To avoid this problem, you should use odd number as signer count.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaintope%2Ftapyrus-signer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchaintope%2Ftapyrus-signer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaintope%2Ftapyrus-signer/lists"}