Closed ethanfrey closed 3 years ago
Decision was made to:
Some comments regarding these signature verification schemes.
All these schemes(except for the Cosmos alternative), use secp256k1.
My question is: At which level our API must handle signature verification for the different blockchains? That is, what are the formats for message, pubkey, and signature, that we must support as inputs in each case?
Moreover: From which sources do you recommend obtaining (or how to generate) messages, signatures and pubkeys that are compatible / valid for each blockchain? So that I can build test examples on how to deserialize them? The issue here seems to be more about deserialization formats and encodings for messages, keys, and signatures, than anything else.
After that, it will be easy for me to wrap and organize the needed methods / structures (probably from different crates), so that this verification functionality is readily available for contracts.
@webmaster128 had made the proposal that we just define one canonical secp256k1 verify function. And the mapping from chain-specific format to this canonical format happen in the wasm contract. If we can produce some examples that do that for Cosmos SDK, Ethereum, and BTC, then I am happy.
One API function, a sample contract with 2 different calls, mapping the various chain formats to the underlying curve
Moreover: From which sources do you recommend obtaining (or how to generate) messages, signatures and pubkeys that are compatible / valid for each blockchain? So that I can build test examples on how to deserialize them? The issue here seems to be more about deserialization formats and encodings for messages, keys, and signatures, than anything else.
Many of us can get a good Cosmos example. Ask in discord, someone in the team may be able to give good Eth or BTC reference data
Thanks for the answers. I'll work in the Cosmos example then (after getting some useful data / examples).
By the way, I've found some data in https://github.com/CosmWasm/wasmd/blob/master/x/wasm/internal/keeper/testdata/genesis.json#L157-L163. I guess the signature is for the json encoded message, above, but I'm not sure. Wonder if this could be useful for tests.
Here you find good set of secp256k1 signatures to test the verification: https://github.com/cosmos/cosmjs/blob/v0.24.0-alpha.22/packages/crypto/src/secp256k1.spec.ts#L195-L517. message
is the encoded transaction data. It goes through sha256 (the prehash) in order to be small enough to fit on the elliptic curve. How message
is created on different chains does not matter to the signature verification API.
Here you find good set of secp256k1 signatures to test the verification: https://github.com/cosmos/cosmjs/blob/v0.24.0-alpha.22/packages/crypto/src/secp256k1.spec.ts#L195-L517.
Unfortunately those do not directly show the public key. It must be calculated from the private key. But I can do that later today.
There is also https://github.com/cosmos/cosmjs/blob/d0833a34f48733407c9947fafb5c773bca8850d6/packages/proto-signing/src/testutils.spec.ts
which is mainly targeting signing, but it has compressed pubkey, signBytes, and signature for 3 test cases. (The pubkey is on the top line outside the test cases, and base64 encoded not hex)
@maurolacy signBytes
is the same as message
from my comment. sha256(signBytes)
/sha256(message)
is what goes into the raw secp256k1 verify algorithm.
Here are the test vectors for the plain contract-vm interface: https://gist.github.com/webmaster128/919f5b505b2f89844f28b90f0c0cf858
secp256k1_verify(message_hash, signature, pubkey)
with
message_hash
: the pre-hash of the message. This ensure the input data is small enough to be used with secp256k1. Cosmos uses SHA256; Ethereum uses Keccak256. But the API does not need to care about the prehashing step, as it can happen in the contract.signature
: A fixed length encoded secp256k1 signature (r, s)
where both r
and s
are big endian encoded integers padded to 32 bytes each. Fixed length encoding is used in Cosmos SDK. Ethereum uses DER, which needs re-encoding (as implemented here).pubkey
: a 65 bytes uncompressed pubkey. Cosmos SDK uses compressed pubkeys, Ethereum uses uncompressed pubkeys. We can have a helper to uncompress later on.As discussed with @ethanfrey, adding batch verify for ed25519 (supported by ed25519-zebra rust crate) would be super useful for the Cosmos IBC Wasm light-client support.
Let's tackle that with ticket #755 First the single verification, then the batch verification (claim up to 20x speedup).
Thank you @joe-bowman. Batch verification of ed25519 signatures has its own ticket now, listed under serious considerations above: #781
This is done. We implemented seck256k1 and Ed25519. If we want to add more algorithms in the future, let's open specific tickets for those. Great jobs and thanks everyone ✌️
There have been a number of requests for suporting various signature verification as "pre-compiles", such as #583 as well as a number of requests in chats. This is an overview ticket to work out what APIs we would like to support. Each individual algorithm should be a separate PR (and maybe a breakout issue). You may also want to address #602 to allow more complex return values in these APIs.
Very important:
Serious Consideration:
bls12_381
curve. Ideally this is general enough to support ZCash's Jubjub on the same bls12_381 curveBonus Points:
alt_bn128
curve (maybe the same as bn256?). Reason to support this particular algorithm is the amount of tooling around Ethereum ZK snark contracts, eg. Zokrates, which may be able to be ported to CosmWasm contract.