Threshold ECDSA Signatures

@dieter.sommer i was not aware of the rationale myself so thank you in explaining it simply enough I can follow (i am by far not in any capacity to opine on Crypto protocols), but I can follow the surprises of performance.

Fwiw, I am grateful to @lastmjs and @skilesare in diving deeper to help us reveal the thinking and memorialize it for others reading this thread.


Thanks for your great work, what you are Achieving is brilliant


what kind of costs are we expecting to call this function?

I think in the order of 10B cycles, but of course it depends on how much performance we can get.

do we expect it to scale horizontally eventually where we can add more t-ecdsa-specific subnets to enable lots of sig/sec?



Does 1 sig/s mean it can only do 1 tps?

Yes. But if demand is higher than this, we can scale out linearly using more signing subnets.

Most of the Bitcoin use on the IC may be anyway through the upcoming ckBTC, i.e., fully on chain on the IC. Only settlement transactions would need to go to the Bitcoin network.

B.t.w., I would be really happy to see 1 trx / sec on the Bitcoin network coming from the IC, that would be around 10% considering the max trx throughput on the Bitcoin network of around 7-10 trx/s. That would be the ultimate success for this feature! :rocket:


It looks like eth evm transactions need “v” in the transaction that specifies which point was used. I see how to get r and s, but what would v be? Is it always the same? Is it per curve?

sign_with_ecdsa: This method returns a new ECDSA signature of the given message_hash that can be separately verified against a derived ECDSA public key. This public key can be obtained by calling ecdsa_public_key with the caller’s canister_id, and the same derivation_path and key_id used here.
The signatures are encoded as the concatenation of the SEC1 encodings of the two values r and s. For curve secp256k1, this corresponds to 32-byte big-endian encoding.

Edit: Looks like you get it from r:

Once we have valid values for r and s , the last piece of the signature is v . This value allows you to calculate the public key from a transaction signature. There are a couple of different ways to derive this, but for our purposes, we’ll just use 37 if r is even and 38 if r is odd, as this follows EIP-155.

Another questions:

The return result is an extended public key consisting of an ECDSA public_key , encoded in SEC1 compressed form, and a chain_code , which can be used to deterministically derive child keys of the public_key .

Is there code anywhere that demonstrates how to derive these sub-addresses using the chain code?

The motoko example: Internet Computer Content Validation Bootstrap

Limits the message hash to 32 bytes. An eth transaction is an arbitrary number of bytes(I’d guess the deployment of a contract could be quite large). Is there a limit to this or a function that we should use to allocate enough cycles for larger strings.

You can sign arbitrary messages, but as per the ECDSA standard, you have to hash the message first. For a number of reasons, we leave it to the canister to hash the message.


This makes sense. So for evm this would be a standard sha256 of the RLP encoded transaction?

Though, in theory, nothing prevents the message itself to be a hash, correct?

I think it’s Keccak for Ethereum.

1TPS? We may therefore need more fees to resist similar DOS attacks?Can the same signature be replicated to multiple subnets? Could we be temporarily frozen funds in the signature by a DOS attack?

1 Like

1TPS? We may therefore need more fees to resist similar DOS attacks?

Yes, the fees will be set to make sure that a subnet burns more ICP than is minted for node providers if all it does is create ECDSA signatures as fast as it can.

Can the same signature be replicated to multiple subnets?

Yes, this 1 signature per second estimate is for one subnet. It can scale out such that many subnets can create ecdsa signatures.

1 Like

I think ic/ at b8b2eca5bc092b1bba072b1fb6c019489f9b7fb3 · dfinity/ic · GitHub does what you are looking for, does that answer your question?

1 Like

Note also that extended BIP32 is compatible with the standard (non-hardened) BIP32 derivation: chain codes and public keys are used in the same way. So if you stick to non-hardened BIP32 derivation paths you should be able to use existing libraries. The only difference with extended BIP32 is that it allows to use longer strings inside the derivation path.

Upon further reflection over the last little while, I’m becoming increasingly concerned about the node operator collusion attack vector. tECDSA has worse BFT properties than ICC, only 1/3 of node operators (secret key share holders) are necessary to collude to create a threshold signature. The current tECDSA subnet has 34 STATIC node operators, meaning that 12 are necessary to collude to sign anything they want.

Is this acceptable security? Is the tECDSA subnet composed of truly independent node operators? Are there 12 independent entities that need to collude, or fewer?

The fact that the subnets are static seems to greatly increase the probability of successful collusion. ICC is based on a static adversary (I’m not sure how related ICC is to tECDSA). Why was this assumption made? This seems woefully inadequate when applying a BFT protocol to the real world.

The decentralization properties (and thus the security properties) of subnets are so very concerning right now. I don’t even feel comfortable calling the IC decentralized at this point, I prefer the term progressively decentralizing. But when are we going to address the static node operator collusion attack vector? It may be of the absolute utmost importance compared with everything else when you consider the consequences.


Another quick point maybe to summarize. tECDSA and the Bitcoin Integration are touted as decentralized and non-custodial solutions. Well actually, we depend in the worst case on only 12 known static entities to custody the key shares and use them appropriately. This seems rather custodial to me. Definitely better than 1 party, but seems pretty similar to other bridging solutions that have a small set of validators tasked with security and bridging.

The obvious solution in my mind is truly weaving the node operators and canisters into one giant logical computer, by making subnet node and maybe even canister membership ephemeral and random. At any time node operators could shuffle and perhaps even canisters, so that subnet membership is not static.

The static threat really scares me.


As someone going on the road and trying to defend and promote this feature at various places like ETHMexico, Science of Blockchain, and the coming DevCon in Bogata…it would be really helpful to have subnet shuffling on the road map in the highest priority slot(along with boundary node decentralization).

We have the feature set that is years ahead of the market if we can follow through with the decentralization part.


Holy moly. Invoke a proposal, if we need subnet shuffling & boundary node decentralisation we need it fast. The IC cannot afford a security blunder, especially with other peoples BTC

1 Like