Transactions are signed used the
decaf377-rdsa construction. As described briefly in that section, there are two signature domains used in Penumbra:
SpendAuth signatures and
SpendAuth signatures are created using a randomized signing key and the corresponding randomized verification key provided on the action. The purpose of the randomization is to prevent linkage of verification keys across actions.
SpendAuth signature is computed using the
where the message to be signed is the effect hash of the entire transaction
(described below), and the
decaf377-rdsa domain is
The effect hash is computed over the effecting data of the transaction, which following the terminology used in Zcash1:
“Effecting data” is any data within a transaction that contributes to the effects of applying the transaction to the global state (results in previously-spendable coins or notes becoming spent, creates newly-spendable coins or notes, causes the root of a commitment tree to change, etc.).
The data that is not effecting data is authorizing data:
“Authorizing data” is the rest of the data within a transaction. It does not contribute to the effects of the transaction on global state, but allows those effects to take place. This data can be changed arbitrarily without resulting in a different transaction (but the changes may alter whether the transaction is allowed to be applied or not).
For example, the nullifier on a
Spend is effecting data, whereas the
proofs or signatures associated with the
Spend are authorizing data.
In Penumbra, the effect hash of each transaction is computed using the BLAKE2b-512 hash function. The effect hash is derived from the proto-encoding of the action - in cases where the effecting data and authorizing data are the same, or the body of the action - in cases where the effecting data and authorizing data are different. Each proto has a unique string associated with it which we call its Type URL, which is included in the inputs to BLAKE2b-512. Type URLs are variable length, so a fixed-length field (8 bytes) is first included in the hash to denote the length of the Type URL field.
Summarizing the above, the effect hash for each action is computed as:
effect_hash = BLAKE2b-512(len(type_url) || type_url || proto_encode(proto))
type_url is the bytes of the variable-length type URL,
len(type_url) is the length of the type URL encoded as 8
bytes in little-endian byte order,
proto represents the proto used to represent
the effecting data, and
proto_encode represents encoding the proto message as
a vector of bytes.
On a per-action basis, the effect hash is computed using the following labels and protos representing the effecting data in Penumbra:
We compute the transaction data field effect hashes in the same manner as actions:
To compute the effect hash of the entire transaction, we combine the hashes of the individual fields in the transaction body. First we include the fixed-sized effect hashes of the per-transaction data fields: the transaction parameters
eh(fee), (optional) detection data
eh(detection_data), and (optional) memo
eh(memo) which are derived as described above. Then, we include the number of actions and the fixed-size effect hash of each action
a_j. Combining all fields:
effect_hash = BLAKE2b-512(len(type_url) || type_url || eh(tx_params) || eh(fee) || eh(memo) || eh(detection_data) || j || eh(a_0) || ... || eh(a_j))
type_url are the bytes
len(type_url) is the length of that string encoded as 8 bytes in little-endian byte order.
Binding signature is computed once on the transaction level.
It is a signature over a hash of the authorizing data of that transaction, called the auth hash. The auth hash of each transaction is computed using the BLAKE2b-512 hash function over the proto-encoding of the entire
Binding signature is computed using the
where the message to be signed is the auth hash as described above, and the
decaf377-rdsa domain is
Binding. The binding signing key is computed using the random blinding factors for each balance commitment.