{"id":26055541,"url":"https://github.com/blockstreamresearch/cross-input-aggregation","last_synced_at":"2025-03-17T14:14:54.816Z","repository":{"id":40936569,"uuid":"360930296","full_name":"BlockstreamResearch/cross-input-aggregation","owner":"BlockstreamResearch","description":"Thoughts on cross-input (signature) aggregation for Bitcoin","archived":false,"fork":false,"pushed_at":"2025-02-28T17:04:34.000Z","size":53,"stargazers_count":60,"open_issues_count":4,"forks_count":10,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-03-08T10:20:13.428Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BlockstreamResearch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2021-04-23T15:35:51.000Z","updated_at":"2025-02-28T17:04:37.000Z","dependencies_parsed_at":"2025-02-28T18:21:27.504Z","dependency_job_id":"547956b6-fe00-4e7e-b296-0c8c425067d6","html_url":"https://github.com/BlockstreamResearch/cross-input-aggregation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlockstreamResearch%2Fcross-input-aggregation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlockstreamResearch%2Fcross-input-aggregation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlockstreamResearch%2Fcross-input-aggregation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlockstreamResearch%2Fcross-input-aggregation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BlockstreamResearch","download_url":"https://codeload.github.com/BlockstreamResearch/cross-input-aggregation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244047646,"owners_count":20389206,"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":[],"created_at":"2025-03-08T10:19:44.992Z","updated_at":"2025-03-17T14:14:54.787Z","avatar_url":"https://github.com/BlockstreamResearch.png","language":"Rust","readme":"# Cross-Input Signature Aggregation (CISA)\n\nCISA is a potential Bitcoin softfork that reduces transaction weight. The purpose of this repository is to collect thoughts and resources on signature aggregation schemes themselves and how they could be integrated into Bitcoin.\n\n## Contents\n\n- [Half Aggregation](#half-aggregation)\n- [Sigagg Case Study: LN Channel Announcements](#sigagg-case-study-ln-channel-announcements)\n- [Integration Into The Bitcoin Protocol](#integration-into-the-bitcoin-protocol)\n  - [Cross-input-aggregation savings](#cross-input-aggregation-savings)\n  - [Half Aggregation And Mempool Caching](#half-aggregation-and-mempool-caching)\n  - [Half Aggregation And Reorgs](#half-aggregation-and-reorgs)\n  - [Half Aggregation And Adaptor Signatures](#half-aggregation-and-adaptor-signatures)\n\n## Half Aggregation\n\nHalf aggregation allows non-interactively aggregating a set of signatures into a single aggregate signature whose size is half of the size of the original signatures.\n\nSee [half-aggregation.mediawiki](half-aggregation.mediawiki) for a detailed description.\nThere is also a [recording of Implementing Half Aggregation in libsecp256k1-zkp](https://www.youtube.com/watch?v=Dns_9jaNPNk) with accompanying [\"slides\"](slides/2021-Q2-halfagg-impl.org).\n\n## Sigagg Case Study: LN Channel Announcements\n\n[Channel announcements messages](https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#the-channel_announcement-message) are gossiped in the Lightning Network to allow nodes to discover routes for payments.\n\nTo prove that a channel between a node with public key `node_1` and a node with public key `node_2` does exist, the announcement contains four signatures.\nFirst, the announcement contains `node_signature_1` and `node_signature_2` which are are signatures over the channel announcement message by `node_1` and `node_2` respectively.\n\nThe channel announcement also proves that the two keys `bitcoin_key_1` and `bitcoin_key_2` contained in the funding output of the funding transaction are owned by `node_1` and `node_2` respectively.\nTherefore, it contains signature `bitcoin_signature_1` by `bitcoin_key_1` over `node_1` and `bitcoin_signature_2` by `bitcoin_key_2` over `node_2`.\n\n1. Since `node_signature_1` and `node_signature_2` are signatures over the same message, one can use a scheme like [MuSig2](https://eprint.iacr.org/2020/1261.pdf) to replace both signatures with a single multisignature `node_signature` that has the same size as an individual signature.\n2. In order to create a channel announcement message, both nodes need to cooperate.\n   Therefore, they can interactively fully aggregate the three signatures into a single aggregate signature.\n3. Channel announcements are often sent in batches.\n   Within a batch, the signatures of all channel announcements can be non-interactively half aggregated since this does not require the communication with the nodes.\n   Each channel announcement signature is thus reduced to a half-aggregated signature which is half the size of the original signature.\n\nAs a result, starting from four signatures (256 bytes) which make up about 60% of a channel announcement today are aggregated into one half signature (32 bytes for a large batch).\n\nOf course, variations of above recipe are possible.\nFor example, if one wants to avoid full aggregation for simplicity's sake, the four signatures in an announcement can just be half aggregated to reduce them to the size of 2.5 signatures.\n\n## Integration Into The Bitcoin Protocol\n\nSince the verification algorithm for half and fully aggregated signatures differs from BIP 340 Schnorr Signature verification, nodes can not simply start to produce and verify aggregated signatures.\nThis would result in a chain split.\n\nTaproot \u0026 Tapscript provide multiple upgrade paths:\n- **Redefine `OP_SUCCESS` to `OP_CHECKAGGSIG`:**\n    As pointed out in [this post to the bitcoin-dev mailing list](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html), an `OP_CHECKAGGSIG` appearing within a script that includes `OP_SUCCESS` can result in a chain split.\n    That's because `OP_CHECKAGGSIG` does not actually verify the signature, but puts the public key in some datastructure against which the aggregate signature is only verified in the end - after having encountered all `OP_CHECKAGGSIG`.\n    While one node sees `OP_SUCCESS OP_CHECKSIGADD`, a node with another upgrade - supposedly a softfork - may see `OP_DOPE OP_CHECKSIGADD`.\n    Since they disagree how to verify the aggregate signature, they will disagree on the verification result which results in a chainsplit.\n    Hence, `OP_CHECKAGGSIG` can't be used in a scripting system with `OP_SUCCESS`.\n    The same argument holds for the attempt to add aggregate signatures via Tapscript's key version.\n- **Define new leaf version to replace tapscript:** If the new scripting system has `OP_SUCCESS` then this does not solve the problem.\n- **Define new SegWit version:**\n    It is possible to define a new SegWit version that is a copy of Taproot \u0026 Tapscript with the exception that all keyspend signatures are allowed to be aggregated.\n    On the other hand, if the goal is that aggregation is _only_ possible for keyspends, then defining a new SegWit version is necessary (since Taproot keyspends expects a BIP-340 signature and not some aggregated signature).\n    However, keyspends can not be aggregated across SegWit versions:\n    nodes that do not recognize the newest SegWit version are not able to pick up the public keys and messages that the aggregate signature is supposed to be verified with.\n\nAssume that a new SegWit version is defined to deploy aggregate signatures by copying Taproot and Tapscript and allowing only keyspends to be aggregated.\nThis would be limiting.\nFor example, a spending policy `(pk(A) and pk(B)) or (pk(A) and older(N))` would usually be instantiated in Taproot by aggregating keys A and B to create a keypath spend and appending a script path for `(pk(A) and older(N))`.\nIt wouldn't be possible to aggregate the signature if the second spending path is used.\n\nThis [bitcoin-dev post](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html) shows that this limitation is indeed unnecessary by introducing Generalized Taproot, a.k.a. g'root  (see also [this post](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html) for a summary).\nEssentially, instead of requiring that each leaf of the taproot merkle tree is a script, in g'root leafs can consist of both a public key and a script.\nIn order to use such a spending path, a signature for the public key must be provided, as well as the inputs to satisfy the script.\nThis means that the public key is moved out of the scripting system, leaving it unencumbered by `OP_SUCCESS` and other potentially dangerous Tapscript components.\nHence, signatures for these public keys _can_ be aggregated.\n\nConsider the example policy `(pk(A) and pk(B)) or (pk(A) and older(N))` from above.\nIn g'root the root key `keyagg((pk(A), pk(B)))` commits via taproot tweaking to a spending condition consisting of public key `pk(A)` and script `older(N)`.\nIn order to spend with the latter path, the script must be satisfied and an _aggregated_ signature for `pk(A)` must exist.\n\nThe [Entroot](https://gist.github.com/sipa/ca1502f8465d0d5032d9dd2465f32603) proposal is a slightly improved version of g'root that integrates Graftroot.\nOne of the main appeals is that Entroot is \"remarkably elegant\" because the validation rules of Entroot are rather simple for the capabilities it enables.\n\n\n### Cross-input Aggregation Savings\n\nSee [savings.org](savings.org).\n\n### Half Aggregation And Mempool Caching\n\nAs mentioned [on bitcoin-dev](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-May/014308.html) nodes accepting a transaction with a half aggregate signature `(s, R_1, ..., R_n)` to their mempool would not throw it away or aggregate it with other signatures.\nInstead, they keep the signature and when a block with block-wide aggregate signature `(s', R'_1, ..., R'_n')` arrives they can subtract `s` from `s'` and remove `R_1, ..., R_n`, from the block-wide aggregate signature before verifying it.\nAs a result, the nodes skip what they have already verified.\n\n### Half Aggregation And Reorgs\n\nAssume there is a transaction `X` with half aggregate signature `S0 = (s0, R_1, ..., R_n)`.\nThe transaction is contained in chain `C1` and therefore there exists a block with a signature `S1` that half aggregates all signatures in the block.\nSince `s0` is aggregated into `S1`, it is not retrievable from the block.\n\nNow there happens to be a reorganization from chain `C1` to chain `C2`.\nThere are the following two cases where half aggregation affects the reorganization.\n\n1. Transaction `X` is contained in both chain `C1` and `C2`.\n   Let `S2` be the block-wide half aggregate signature of the block in `C2` that conatains `X`.\n   In general `S1 != S2`, so the whole half-aggregate signature `S2` must be verified, including the contribution of `X` despite having it verified already.\n   If `s0` was kept, it could be subtracted from `S2`.\n   This is in contrast to ordinary signatures, which do not have to be re-verified in a reorg.\n2. Transaction `X` is contained in `C1` but not in `C2`.\n   Because we can't recover `s0`, we can't broadcast transaction `X`, nor can we build a block that includes it.\n   Hence, we can't meaningfully put `X` back into the mempool.\n\nBoth cases would indicate that it is beneficial to keep `s0` even though the transaction is included in the best chain.\nOnly when the transaction is buried so deep that reorgs can be ruled out, the value `s0` can be discarded.\n\nAnother solution for case 2. is to have the participants of the transaction (such as sender and receiver) rebroadcast the transaction.\nBut this may have privacy issues.\n\n### Half Aggregation And Adaptor Signatures\n\nHalf aggregation prevents using adaptor signatures ([stackexchange](https://bitcoin.stackexchange.com/questions/107196/why-does-blockwide-signature-aggregation-prevent-adaptor-signatures)).\nHowever, a new SegWit version as outlined in section [Integration Into The Bitcoin Protocol](#integration-into-the-bitcoin-protocol) would keep signatures inside Tapscript unaggregatable.\nHence, protocols using adaptor signatures can be instantiated by having adaptor signatures only appear inside Tapscript.\n\nThis should not be any less efficient in g'root if the output can be spend directly with a script, i.e., without showing a merkle proof.\nHowever, since this is not a normal keypath spend and explicitly unaggregatable, such a spend will stick out from other transactions.\nIt is an open question if this actually affects protocols built on adaptor signatures.\nIn other words, can such protocols can be instantiated with a Tapscript spending path for the adaptor signature but without having to use actually use that path - at least in the cooperative case?\nSee [half-agg-and-adaptor-sigs.md](half-agg-and-adaptor-sigs.md) for more discussion on this subject.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblockstreamresearch%2Fcross-input-aggregation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblockstreamresearch%2Fcross-input-aggregation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblockstreamresearch%2Fcross-input-aggregation/lists"}