@@ -9,13 +9,20 @@ import (
99 "github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
1010)
1111
12- // ProposalSignatureContext is the context used for signing propose batch dispatch messages .
12+ // ProposalSignatureContext is the context used for signing proposal headers .
1313var ProposalSignatureContext = signature .NewContext (
1414 "oasis-core/roothash: proposal" ,
1515 signature .WithChainSeparation (),
1616 signature .WithDynamicSuffix (" for runtime " , common .NamespaceHexSize ),
1717)
1818
19+ // ProposalBatchSignatureContext is the context used for signing proposal batches.
20+ var ProposalBatchSignatureContext = signature .NewContext (
21+ "oasis-core/roothash: proposal batch" ,
22+ signature .WithChainSeparation (),
23+ signature .WithDynamicSuffix (" for runtime " , common .NamespaceHexSize ),
24+ )
25+
1926// ProposalHeader is the header of the batch proposal.
2027type ProposalHeader struct {
2128 // Round is the proposed round number.
@@ -67,9 +74,17 @@ type Proposal struct {
6774 // Signature is the proposal header signature.
6875 Signature signature.RawSignature `json:"sig"`
6976
70- // Batch is an ordered list of all transaction hashes that should be in a batch. In case of
71- // the proposal being submitted as equivocation evidence, this field should be omitted.
77+ // Batch is an ordered list of all transaction hashes that should be in a batch.
78+ //
79+ // In case of the proposal being submitted as equivocation evidence,
80+ // this field should be omitted.
7281 Batch []hash.Hash `json:"batch,omitempty"`
82+
83+ // BatchSignature is the proposal batch signature.
84+ //
85+ // In case of the proposal being submitted as equivocation evidence,
86+ // this field should be omitted.
87+ BatchSignature * signature.RawSignature `json:"batch_sig,omitempty"`
7388}
7489
7590// Sign signs the proposal header and sets the signature on the proposal.
@@ -83,6 +98,23 @@ func (p *Proposal) Sign(signer signature.Signer, runtimeID common.Namespace) err
8398 return err
8499 }
85100 p .Signature = * sig
101+
102+ // TODO: Sign the batch once most of the compute nodes have been upgraded to a version
103+ // that supports batch signatures.
104+ if false {
105+ batchSigCtx , err := ProposalBatchSignatureContext .WithSuffix (runtimeID .String ())
106+ if err != nil {
107+ return fmt .Errorf ("roothash/commitment: batch signature context error: %w" , err )
108+ }
109+
110+ signature , err := signature .Sign (signer , batchSigCtx , cbor .Marshal (p .Batch ))
111+ if err != nil {
112+ return err
113+ }
114+
115+ p .BatchSignature = & signature .Signature
116+ }
117+
86118 return nil
87119}
88120
@@ -96,5 +128,17 @@ func (p *Proposal) Verify(runtimeID common.Namespace) error {
96128 if ! p .NodeID .Verify (sigCtx , cbor .Marshal (p .Header ), p .Signature [:]) {
97129 return fmt .Errorf ("roothash/commitment: signature verification failed" )
98130 }
131+
132+ if p .BatchSignature != nil {
133+ batchSigCtx , err := ProposalBatchSignatureContext .WithSuffix (runtimeID .String ())
134+ if err != nil {
135+ return fmt .Errorf ("roothash/commitment: batch signature context error: %w" , err )
136+ }
137+
138+ if ! p .NodeID .Verify (batchSigCtx , cbor .Marshal (p .Batch ), p .BatchSignature [:]) {
139+ return fmt .Errorf ("roothash/commitment: batch signature verification failed" )
140+ }
141+ }
142+
99143 return nil
100144}
0 commit comments