-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CKB_TX_MESSAGE_ALL specification proposal #446
base: master
Are you sure you want to change the base?
Conversation
Historically, a particular `message` calculation algorithm has been [introduced](https://github.com/nervosnetwork/ckb-system-scripts/blob/934166406fafb33e299f5688a904cadb99b7d518/c/secp256k1_blake160_sighash_all.c#L149-L219) by lock scripts included in CKB's genesis blocks, and used since then. Many other locks from the community have also adopted a similar workflow. However, this workflow has only since existed in part of a script's implementation. It has never been properly documented. On the other hand, certain pitfalls of this very workflow arise as we learn more about coding for CKB's particular environment: | ||
|
||
* While the current workflow assumes the first witness of current executed input cells [script group](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md) is a [WitnessArgs](https://github.com/nervosnetwork/ckb/blob/a6733e6af5bb0da7e34fb99ddf98b03054fa9d4a/util/types/schemas/blockchain.mol#L104-L108) structure serialized in the [molecule](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0008-serialization/0008-serialization.md) serialization format, this particular assumption is not enforced, and there is code that [exploits](https://github.com/cryptape/quantum-resistant-lock-script/blob/22de5369b60b1e59bb698927c143d9efbe8527a9/c/ckb-sphincsplus-lock.c#L67-L80) this oversight for certain gains. We do believe this can be a problem as future standards arise. | ||
* The current workflow covers the whole [Transaction](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md) structure, as well as all witnesses from the current script group. However, the `Transaction` structure only contains pointer to all the consumed input cells, it does not cover any contents of the input cells, e.g., the CKBytes store in each input cell, or any input cell's data. This makes it harder to design a proper offline signing protocol. If we dig through the literature, the Bitcoin community actually made the same choice early, but later [came up](https://en.bitcoin.it/wiki/BIP_0143) with an updated design, that signs actual contents of each input UTXOs as well. We do believe a message that covers all input cells' contents can definitely bring merits to future CKB wallets & appliations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo appliations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, the
Transaction
structure only contains pointer to all the consumed input cells, it does not cover any contents of the input cells, e.g., the CKBytes store in each input cell, or any input cell's data
This part explains what the current transaction hash captures, am i correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If yes, with a replace by fee feature enabled, and since transaction hash doesn't capture the CKBytes, can the following happen?
Alice sends Bob 100 ckb using her 500ckb cell, get 400 in change.
Nothing stops Bob to take that same signature and add to a new transaction that says:
Alice sends Bob 400ckb using her 500ckb cell, get 100 in change.
Bob broadcast + prioritize it and get 400, instead of 100?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you slightly misunderstand the following lines:
the Transaction structure only contains pointer to all the consumed input cells
Yes a transaction hash does not cover the actual contents of input cells(e.g., CKBytes of each input cell), however transaction hash does cover OutPoint
in CellInput
structure, which can be viewed as a pointer to an input cell. This pointer, already helps guard against manipulating input cells in a signed CKB transactions:
Your described attacks won't happen due to several reasons:
- First of all,
Alice sends Bob 100 ckb
orAlice sends Bob 400 ckb
will be represented as an output cell to Bob. This means the new transaction has an output cell changed, the transaction hash naturally changed, the old signature won't work - Even if we fit the output cell different, say a transaction
Alice sends Bob 400 ckb using her 500 ckb cell, get 99 in change, using 1 ckb as fees
, then someone(most likely a miner) changes it toAlice sends Bob 400 ckb using her 1000 ckb cell, get 99 in change, using 501 ckb as fees
, now all output cells stay the same, so the problem described in the first bullet point won't happen. However, we still need to perform the attack, by swaping one input cells to a different one, 2 solutions exist:
** We could simply change oneOutPoint
in one ofCellInput
structure from the transaction to point to a new cell which holds 1000 ckb from Alice, however, this means oneCellInput
structure is changed in the old transaction, the transaction hash in the new transaction changes as well. The signature validating flow changes
** If we cannot change anything from the signed transaction, the question now is shifted to: can we increase the CKBytes stored in a cell on-chain, while also keeping theOutPoint
used to reference this on-chain cell the same? To me this is an even harder task, I don't have a way to make it happen now, let me know if you believe such attacks exist.
To summarize here, I don't personally believe the old, current way of signing transactions in CKB has any weak points so one can manipulate a transaction after it is signed. However, being secure on chain is not enough sometimes, CIGHASH_ALL
enhances the workflow by signing contents from input cells as well, simply to make offline signing easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for clarifying. You're right i misunderstood the line
will be represented as an output cell to Bob. This means the new transaction has an output cell changed, the transaction hash naturally changed
This should clear things up.
@XuJiandong All typos have been fixed |
|
||
As a result, this document aims to propose `CIGHASH_ALL`, a properly defined message calculation scheme used by CKB lock scripts to ensure transactions are not malleable. | ||
|
||
The name `CIGHASH_ALL` comes from `CKB's Signature Hash All`. In many places, including [filename](https://github.com/nervosnetwork/ckb-system-scripts/blob/master/c/secp256k1_blake160_sighash_all.c) from CKB's system script code, `SIGHASH_ALL` has been used to represent the old workflow to calculate a signing message. Here we explicitly pick a different name, so as to distinguish between the two. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest choosing a better name. CIGHASH_ALL
can easily cause confusion, as it sounds the same as SIGHASH_ALL
and a single char typo could turn it into SIGHASH_ALL
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some other names I can think of is CKB_HASH_ALL
, CKB_SIGHASH_ALL
, CKB_MSGHASH_ALL
, or any other suggestions are welcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nervos's sighash_all
uses an algorithm that aligns with Bitcoin's pre-SegWit SIGHASH, so inputs metadata is not included in the message to sign.
Bitcoin tackled this in BIP143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
Maybe we can directly or indirectly reference BIP143/SegWit in the name 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, I personally don't care about what the name is, I just care about the fact that a commonly-agreed name is decided here. So I will leave this comment as it is, and will always be happy to modify the name to whatever is chosen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some thoughts, I suggest the name CKB_SIGHASH_ALL
. I will leave this name here for a few days, if no further questions arise, I will make the actual changes here.
EDIT: personally, I feel it necessary to acknowledge BIP143 in the RFC spec definition, but I think it is not appropriate to include BIP143 in the name of the new spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To combine the above comments, I would suggest a different name here: CKB_TX_MESSAGE_ALL
, it consists of 3 parts:
- The
CKB_TX_
prefix works as a namespace denoting that we are building a specification for CKB transactions. Let's be nice to the whole blockchain community, to avoid a name that is too general MESSAGE
has 2 advantages: first, it helps avoid confusion withSIGHASH
; second, if you think about the above defined specification and the reference implementation, we are not really designing a hash here, we are designing a spec which is a series of concatenated bytes, you can keep the bytes as it is, or you can feed them into a hash. So what we have here, really is a message, not necessarily a hash.- The final suffix defines the range of the transaction to include in the message. Personally, I think
all
andfull
are both fine but semantically speaking I fellall
is slightly better when I checked the dictionary. But I'm not a native English speaker, @Matt-RUN-CKB @jordanmack care to weigh in here?
So my current suggestion would be CKB_TX_MESSAGE_ALL
. Like the previous one, I'm gonna keep it here for a few days, and will actually make the change later if no further comments are received.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even CKB_MESSAGE_FULL
sounds good 👍 (I'm not a native English speaker tho)
About that TX
, what's the reason for its inclusion? Can you foresee a possible future where messages are created from non-TX entities?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About that TX, what's the reason for its inclusion? Can you foresee a possible future where messages are created from non-TX entities?
CKB is more than just transactions and scripting part, there might be also messages in other parts, such as p2p layers and others. Adding TX
as part of suffix make it more precise and future proof.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we haven't heard more on the suggestions, I've renamed the specification from CIGHASH_ALL
to CKB_TX_MESSAGE_ALL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, for sure it's an improvement over CIGHASH_ALL
👍
CKB_SIGHASH143 in homage to the king |
Congratulations @xxuejie on the proposal!! I fully support the idea 🔥 Are we able to tackle also another problem, possibly within this proposal? (if makes sense) During the internal review iCKB was rightfully slapped with Malleability of unsigned lock witnesses. This is not really an iCKB problem, but a The underlying issue is that in As more and more protocols start using non-signature-based locks and also start using the witness to store data, this issue is gonna become more and more evident. Are we able to do something about the malleability of unsigned lock witnesses with this proposal? Love & Peace, Phroi |
PS: maybe it's already fixed in its current proposal specification, I still have to study the implementation details. I just want to be sure that the malleability of unsigned lock witnesses is fully considered before this proposal moves to the next steps 🙏 |
I personally question the necessity of non-signature based locks at all. If I were doing the design, I would use types solely for non-signature based locks. In addition, this design is specifically addressed to locks that do require a signature, and want the signature to guard enough entities. A separate design will be needed, even if we want to have non-signature based locks. |
This is indeed the best-practice, but sometimes I cannot see a way to apply it. Please, let's continue this topic on Nervos Talk!! 🤗
while keeping all the rest as unchanged as possible: backward compatibility at its finest, gotcha!! I don't know, it feels a bit like a missed opportunity for laying the bases for future work, so for forward compatibility. Well, if anybody else feels the same, feel free to pitch-in! Love & Peace, Phroi |
PREVIEW LINK