Skip to content

Commit

Permalink
go/roothash: Optional root hashes in compute commitments headers
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrus committed Oct 9, 2020
1 parent 60491d1 commit d5d902f
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 33 deletions.
4 changes: 2 additions & 2 deletions go/consensus/tendermint/apps/roothash/roothash.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,8 @@ func (app *rootHashApplication) tryFinalizeExecutorCommits(
hdr := commit.ToDDResult().(commitment.ComputeResultsHeader)

blk := block.NewEmptyBlock(rtState.CurrentBlock, uint64(ctx.Now().Unix()), block.Normal)
blk.Header.IORoot = hdr.IORoot
blk.Header.StateRoot = hdr.StateRoot
blk.Header.IORoot = *hdr.IORoot
blk.Header.StateRoot = *hdr.StateRoot
// Messages omitted on purpose.

// Timeout will be cleared by caller.
Expand Down
6 changes: 3 additions & 3 deletions go/oasis-node/cmd/debug/byzantine/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ func (cbc *computeBatchContext) createCommitment(id *identity.Identity, rak sign
header := commitment.ComputeResultsHeader{
Round: cbc.bd.Header.Round + 1,
PreviousHash: cbc.bd.Header.EncodedHash(),
IORoot: cbc.newIORoot,
StateRoot: cbc.newStateRoot,
IORoot: &cbc.newIORoot,
StateRoot: &cbc.newStateRoot,
// TODO: allow script to set roothash messages?
Messages: []*block.Message{},
}
Expand All @@ -278,7 +278,7 @@ func (cbc *computeBatchContext) createCommitment(id *identity.Identity, rak sign
return fmt.Errorf("signature Sign RAK: %w", err)
}

computeBody.RakSig = rakSig.Signature
computeBody.RakSig = &rakSig.Signature
}
var err error
cbc.commit, err = commitment.SignExecutorCommitment(id.NodeSigner, computeBody)
Expand Down
25 changes: 16 additions & 9 deletions go/roothash/api/commitment/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ var (
//
// Keep the roothash RAK validation in sync with changes to this structure.
type ComputeResultsHeader struct {
Round uint64 `json:"round"`
PreviousHash hash.Hash `json:"previous_hash"`
IORoot hash.Hash `json:"io_root"`
StateRoot hash.Hash `json:"state_root"`
Messages []*block.Message `json:"messages"`
Round uint64 `json:"round"`
PreviousHash hash.Hash `json:"previous_hash"`

// Optional fields (may be absent for failure indication).

IORoot *hash.Hash `json:"io_root,omitempty"`
StateRoot *hash.Hash `json:"state_root,omitempty"`
Messages []*block.Message `json:"messages,omitempty"`
}

// IsParentOf returns true iff the header is the parent of a child header.
Expand Down Expand Up @@ -78,8 +81,8 @@ type ComputeBody struct {

// Optional fields (may be absent for failure indication).

StorageSignatures []signature.Signature `json:"storage_signatures,omitempty"`
RakSig signature.RawSignature `json:"rak_sig,omitempty"`
StorageSignatures []signature.Signature `json:"storage_signatures,omitempty"`
RakSig *signature.RawSignature `json:"rak_sig,omitempty"`
}

// VerifyTxnSchedSignature rebuilds the batch dispatch message from the data
Expand All @@ -98,9 +101,13 @@ func (m *ComputeBody) VerifyTxnSchedSignature(header block.Header) bool {
// RootsForStorageReceipt gets the merkle roots that must be part of
// a storage receipt.
func (m *ComputeBody) RootsForStorageReceipt() []hash.Hash {
if m.Header.IORoot == nil || m.Header.StateRoot != nil {
return nil
}

return []hash.Hash{
m.Header.IORoot,
m.Header.StateRoot,
*m.Header.IORoot,
*m.Header.StateRoot,
}
}

Expand Down
34 changes: 33 additions & 1 deletion go/roothash/api/commitment/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var (
ErrBadStorageReceipts = errors.New(moduleName, 14, "roothash/commitment: bad storage receipts")
ErrTimeoutNotCorrectRound = errors.New(moduleName, 15, "roothash/commitment: timeout not for correct round")
ErrNodeIsScheduler = errors.New(moduleName, 16, "roothash/commitment: node is scheduler")
ErrBadRootHashes = errors.New(moduleName, 17, "roothash/commitment: commitment has invalid root hashes")
)

const (
Expand Down Expand Up @@ -240,8 +241,24 @@ func (p *Pool) addOpenExecutorCommitment(

switch body.Failure {
case FailureNone:
// Ensure header fields are present.
if header.IORoot == nil {
logger.Debug("executor commitment is missing IORoot")
return ErrBadRootHashes
}

// Ensure header fields are present.
if header.StateRoot == nil {
logger.Debug("executor commitment is missing StateRoot")
return ErrBadRootHashes
}

// Verify RAK-attestation.
if p.Runtime.TEEHardware != node.TEEHardwareInvalid {
if body.RakSig == nil {
logger.Debug("executor commitment is missing RAK signature")
return ErrRakSigInvalid
}
n, err := nl.Node(ctx, id)
if err != nil {
// This should never happen as nodes cannot disappear mid-epoch.
Expand Down Expand Up @@ -302,8 +319,23 @@ func (p *Pool) addOpenExecutorCommitment(
return ErrBadStorageReceipts
}

// Ensure header fields are empty.
if header.IORoot != nil {
logger.Debug("failure indicating executor commitment includes IORoot",
"io_root", header.IORoot,
)
return ErrBadRootHashes
}

if header.StateRoot != nil {
logger.Debug("failure indicating executor commitment includes StateRoot",
"io_root", header.IORoot,
)
return ErrBadRootHashes
}

// In case of failure indicating commitment make sure RAK signature is empty.
if !body.RakSig.Equal(signature.RawSignature{}) {
if body.RakSig != nil {
logger.Debug("failure indicating commitment includes RAK signature",
"node_id", id,
"rak_sig", body.RakSig.String(),
Expand Down
31 changes: 21 additions & 10 deletions go/roothash/api/commitment/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ func TestPoolDefault(t *testing.T) {
Header: ComputeResultsHeader{
Round: blk.Header.Round,
PreviousHash: blk.Header.PreviousHash,
IORoot: blk.Header.IORoot,
StateRoot: blk.Header.StateRoot,
IORoot: &blk.Header.IORoot,
StateRoot: &blk.Header.StateRoot,
},
}
commit, err := SignExecutorCommitment(sk, &body)
Expand Down Expand Up @@ -176,7 +176,19 @@ func TestPoolSingleCommitment(t *testing.T) {
{"BlockBadRound", func(b *ComputeBody) { b.Header.Round-- }, ErrNotBasedOnCorrectBlock},
{"BlockBadPreviousHash", func(b *ComputeBody) { b.Header.PreviousHash.FromBytes([]byte("invalid")) }, ErrNotBasedOnCorrectBlock},
{"StorageSigs1", func(b *ComputeBody) { b.StorageSignatures = nil }, ErrBadStorageReceipts},
{"MissingIORootHash", func(b *ComputeBody) { b.Header.IORoot = nil }, ErrBadRootHashes},
{"MissingStateRootHash", func(b *ComputeBody) { b.Header.StateRoot = nil }, ErrBadRootHashes},
{"FailureIndicatingWithStorageSigs", func(b *ComputeBody) { b.Failure = FailureStorageUnavailable }, ErrBadStorageReceipts},
{"FailureIndicatingWithStateRootHash", func(b *ComputeBody) {
b.Failure = FailureStorageUnavailable
b.StorageSignatures = nil
b.Header.StateRoot = nil
}, ErrBadRootHashes},
{"FailureIndicatingWithIORootHash", func(b *ComputeBody) {
b.Failure = FailureStorageUnavailable
b.StorageSignatures = nil
b.Header.IORoot = nil
}, ErrBadRootHashes},
} {
_, _, invalidBody := generateComputeBody(t)
invalidBody.StorageSignatures = append([]signature.Signature{}, body.StorageSignatures...)
Expand Down Expand Up @@ -310,7 +322,7 @@ func TestPoolSingleCommitmentTEE(t *testing.T) {
childBlk, _, body := generateComputeBody(t)
rakSig, err := signature.Sign(skRAK, ComputeResultsHeaderSignatureContext, cbor.Marshal(body.Header))
require.NoError(t, err, "Sign")
body.RakSig = rakSig.Signature
body.RakSig = &rakSig.Signature

commit, err := SignExecutorCommitment(sk, &body)
require.NoError(t, err, "SignExecutorCommitment")
Expand Down Expand Up @@ -414,7 +426,8 @@ func TestPoolTwoCommitments(t *testing.T) {
correctHeader := body.Header

// Update state root and fix the storage receipt.
body.Header.StateRoot.FromBytes([]byte("discrepancy"))
badHash := hash.NewFromBytes([]byte("discrepancy"))
body.Header.StateRoot = &badHash
body.StorageSignatures = []signature.Signature{generateStorageReceiptSignature(t, parentBlk, &body)}

commit2, err := SignExecutorCommitment(sk2, &body)
Expand Down Expand Up @@ -604,9 +617,9 @@ func TestTryFinalize(t *testing.T) {
correctHeader := body.Header

// Update state root and fix the storage receipt.
body.Header.StateRoot.FromBytes([]byte("discrepancy"))
badHash := hash.NewFromBytes([]byte("discrepancy"))
body.Header.StateRoot = &badHash
body.StorageSignatures = []signature.Signature{generateStorageReceiptSignature(t, parentBlk, &body)}

commit2, err := SignExecutorCommitment(sk2, &body)
require.NoError(t, err, "SignExecutorCommitment")

Expand Down Expand Up @@ -801,8 +814,6 @@ func TestPoolFailureIndicatingCommitment(t *testing.T) {
Header: ComputeResultsHeader{
Round: body.Header.Round,
PreviousHash: body.Header.PreviousHash,
IORoot: body.Header.IORoot,
StateRoot: body.Header.StateRoot,
},
Failure: FailureStorageUnavailable,
}
Expand Down Expand Up @@ -936,8 +947,8 @@ func generateComputeBody(t *testing.T) (*block.Block, *block.Block, ComputeBody)
Header: ComputeResultsHeader{
Round: parentBlk.Header.Round,
PreviousHash: parentBlk.Header.PreviousHash,
IORoot: parentBlk.Header.IORoot,
StateRoot: parentBlk.Header.StateRoot,
IORoot: &parentBlk.Header.IORoot,
StateRoot: &parentBlk.Header.StateRoot,
},
}

Expand Down
4 changes: 2 additions & 2 deletions go/roothash/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ func (s *runtimeState) generateExecutorCommitments(t *testing.T, consensus conse
Header: commitment.ComputeResultsHeader{
Round: parent.Header.Round,
PreviousHash: parent.Header.PreviousHash,
IORoot: parent.Header.IORoot,
StateRoot: parent.Header.StateRoot,
IORoot: &parent.Header.IORoot,
StateRoot: &parent.Header.StateRoot,
},
StorageSignatures: parent.Header.StorageSignatures,
InputRoot: hash.Hash{},
Expand Down
4 changes: 2 additions & 2 deletions go/runtime/host/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ func (r *runtime) Call(ctx context.Context, body *protocol.Body) (*protocol.Body
Header: commitment.ComputeResultsHeader{
Round: rq.Block.Header.Round + 1,
PreviousHash: rq.Block.Header.EncodedHash(),
IORoot: ioRoot,
StateRoot: stateRoot,
IORoot: &ioRoot,
StateRoot: &stateRoot,
},
IOWriteLog: ioWriteLog,
},
Expand Down
11 changes: 7 additions & 4 deletions go/worker/compute/executor/committee/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ func (n *Node) proposeBatchLocked(processedBatch *processedBatch) {
// Generate proposed compute results.
proposedResults := &commitment.ComputeBody{
Header: batch.Header,
RakSig: batch.RakSig,
RakSig: &batch.RakSig,
TxnSchedSig: state.batch.txnSchedSignature,
InputRoot: state.batch.ioRoot.Hash,
InputStorageSigs: state.batch.storageSignatures,
Expand All @@ -1111,14 +1111,14 @@ func (n *Node) proposeBatchLocked(processedBatch *processedBatch) {
{
SrcRound: lastHeader.Round + 1,
SrcRoot: state.batch.ioRoot.Hash,
DstRoot: batch.Header.IORoot,
DstRoot: *batch.Header.IORoot,
WriteLog: batch.IOWriteLog,
},
// State root.
{
SrcRound: lastHeader.Round,
SrcRoot: lastHeader.StateRoot,
DstRoot: batch.Header.StateRoot,
DstRoot: *batch.Header.StateRoot,
WriteLog: batch.StateWriteLog,
},
}
Expand Down Expand Up @@ -1171,6 +1171,9 @@ func (n *Node) proposeBatchLocked(processedBatch *processedBatch) {
n.logger.Error("storage failure, sibmitting failure indicating commitment",
"err", storageErr,
)
proposedResults.RakSig = nil
proposedResults.Header.IORoot = nil
proposedResults.Header.StateRoot = nil
proposedResults.Failure = commitment.FailureStorageUnavailable
}

Expand Down Expand Up @@ -1205,7 +1208,7 @@ func (n *Node) proposeBatchLocked(processedBatch *processedBatch) {
n.transitionLocked(StateWaitingForFinalize{
batchStartTime: state.batchStartTime,
raw: processedBatch.raw,
proposedIORoot: proposedResults.Header.IORoot,
proposedIORoot: *proposedResults.Header.IORoot,
})
default:
n.abortBatchLocked(err)
Expand Down

0 comments on commit d5d902f

Please sign in to comment.