From 04452e28ffc2776c96289263abf2b12bc9841481 Mon Sep 17 00:00:00 2001 From: Cassandra Heart Date: Fri, 10 Jan 2025 12:15:56 -0600 Subject: [PATCH] handle worker failure condition by allowing tree production to continue --- node/config/version.go | 2 +- node/consensus/data/main_data_loop.go | 2 +- .../token_handle_prover_join_test.go | 17 ++++--- node/tries/proof_leaf.go | 14 +----- node/tries/proof_leaf_test.go | 48 +++++++++++++++++++ 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/node/config/version.go b/node/config/version.go index 4430859..74f6c11 100644 --- a/node/config/version.go +++ b/node/config/version.go @@ -43,7 +43,7 @@ func FormatVersion(version []byte) string { } func GetPatchNumber() byte { - return 0x00 + return 0x01 } func GetRCNumber() byte { diff --git a/node/consensus/data/main_data_loop.go b/node/consensus/data/main_data_loop.go index f3616d5..c56f611 100644 --- a/node/consensus/data/main_data_loop.go +++ b/node/consensus/data/main_data_loop.go @@ -233,7 +233,7 @@ func (e *DataClockConsensusEngine) processFrame( latestFrame *protobufs.ClockFrame, dataFrame *protobufs.ClockFrame, ) *protobufs.ClockFrame { - + e.logger.Info( "current frame head", zap.Uint64("frame_number", dataFrame.FrameNumber), diff --git a/node/execution/intrinsics/token/application/token_handle_prover_join_test.go b/node/execution/intrinsics/token/application/token_handle_prover_join_test.go index 706c412..85d6134 100644 --- a/node/execution/intrinsics/token/application/token_handle_prover_join_test.go +++ b/node/execution/intrinsics/token/application/token_handle_prover_join_test.go @@ -109,7 +109,7 @@ func (p *prover) generateTransfer(coin []byte) *protobufs.TokenRequest { func (p *prover) generateSplit(addr []byte) *protobufs.TokenRequest { payload := []byte("split") payload = append(payload, addr...) - bi1, _ := new(big.Int).SetString("2047999999999", 10) + bi1, _ := new(big.Int).SetString("2048000000000", 10) bi2, _ := new(big.Int).SetString("2048000000000", 10) payload = append(payload, bi1.FillBytes(make([]byte, 32))...) payload = append(payload, bi2.FillBytes(make([]byte, 32))...) @@ -174,6 +174,7 @@ func (p *prover) generateProof( proofTree *merkletree.MerkleTree, breakWesoProof bool, breakTreeProof bool, + treeRecovery bool, ) (*merkletree.MerkleTree, [][]byte, *protobufs.TokenRequest) { challenge := []byte{} challenge = append(challenge, []byte(p.peerId)...) @@ -182,7 +183,11 @@ func (p *prover) generateProof( frame.FrameNumber, ) outs := []merkletree.DataBlock{} - for i := 0; i < 64; i++ { + target := 8 + if treeRecovery { + target = 4 + } + for i := 0; i < target; i++ { individualChallenge := append([]byte{}, challenge...) individualChallenge = binary.BigEndian.AppendUint32( individualChallenge, @@ -314,7 +319,7 @@ func TestHandleProverJoin(t *testing.T) { proofTrees := []*merkletree.MerkleTree{} reqs := []*protobufs.TokenRequest{} for _, prover := range provers { - proofTree, _, req := prover.generateProof(frame2, wprover, nil, false, false) + proofTree, _, req := prover.generateProof(frame2, wprover, nil, false, false, false) proofTrees = append(proofTrees, proofTree) reqs = append(reqs, req) } @@ -363,7 +368,7 @@ func TestHandleProverJoin(t *testing.T) { txn.Commit() for i, prover := range provers { - proofTree, _, req := prover.generateProof(frame3, wprover, proofTrees[i], false, false) + proofTree, _, req := prover.generateProof(frame3, wprover, proofTrees[i], false, false, true) proofTrees[i] = proofTree reqs[i] = req } @@ -407,7 +412,7 @@ func TestHandleProverJoin(t *testing.T) { err = txn.Commit() assert.NoError(t, err) assert.Len(t, success.Requests, 1) - assert.Len(t, app.TokenOutputs.Outputs, 3) + assert.Len(t, app.TokenOutputs.Outputs, 2) txn, _ = app.ClockStore.NewTransaction(false) frame4, _ := wprover.ProveDataClockFrame(frame3, [][]byte{}, []*protobufs.InclusionAggregateProof{}, bprivKey, time.Now().UnixMilli(), 10000) @@ -417,7 +422,7 @@ func TestHandleProverJoin(t *testing.T) { txn.Commit() for i, prover := range provers { - proofTree, _, req := prover.generateProof(frame4, wprover, proofTrees[i], false, false) + proofTree, _, req := prover.generateProof(frame4, wprover, proofTrees[i], false, false, true) proofTrees[i] = proofTree reqs[i] = req } diff --git a/node/tries/proof_leaf.go b/node/tries/proof_leaf.go index fb1f137..476d912 100644 --- a/node/tries/proof_leaf.go +++ b/node/tries/proof_leaf.go @@ -59,12 +59,7 @@ func PackOutputIntoPayloadAndProof( binary.BigEndian.AppendUint64([]byte{}, frame.FrameNumber), } - if previousTree != nil { - // don't let node produce invalid proofs that would otherwise fail - if len(previousTree.Proofs) != modulo { - return nil, nil, errors.Wrap(errors.New("invalid tree size"), "pack output into payload and proof") - } - + if previousTree != nil && len(previousTree.Proofs) == modulo { hash := sha3.Sum256(frame.Output) pick := BytesToUnbiasedMod(hash, uint64(modulo)) if uint64(modulo) < pick { @@ -119,12 +114,7 @@ func PackOutputIntoMultiPayloadAndProof( binary.BigEndian.AppendUint64([]byte{}, frame.FrameNumber), } - if previousTree != nil { - // don't let node produce invalid proofs that would otherwise fail - if len(previousTree.Proofs) != modulo { - return nil, nil, errors.Wrap(errors.New("invalid tree size"), "pack output into payload and proof") - } - + if previousTree != nil && len(previousTree.Proofs) == modulo { hash := sha3.Sum256(append(append([]byte{}, frame.Output...), previousTree.Root...)) pick := BytesToUnbiasedMod(hash, uint64(modulo)) if uint64(modulo) < pick { diff --git a/node/tries/proof_leaf_test.go b/node/tries/proof_leaf_test.go index 6dc1bc2..ce3b9c0 100644 --- a/node/tries/proof_leaf_test.go +++ b/node/tries/proof_leaf_test.go @@ -298,3 +298,51 @@ func TestPackAndVerifyMultiOutput(t *testing.T) { }) } } + +func TestPackAndVerifyOutputFailover(t *testing.T) { + outputs := make([]mt.DataBlock, 3) + for i := range outputs { + data := make([]byte, 32) + binary.BigEndian.PutUint32(data, uint32(i)) + outputs[i] = tries.NewProofLeaf(data) + } + + frame := &protobufs.ClockFrame{ + FrameNumber: 1, + Output: make([]byte, 516), + } + rand.Read(frame.Output) + + var previousTree *mt.MerkleTree + prevOutputs := make([]mt.DataBlock, 4) + for i := range prevOutputs { + data := make([]byte, 32) + binary.BigEndian.PutUint32(data, uint32(i)) + prevOutputs[i] = tries.NewProofLeaf(data) + } + + var err error + previousTree, err = mt.New( + &mt.Config{ + HashFunc: func(data []byte) ([]byte, error) { + hash := sha3.Sum256(data) + return hash[:], nil + }, + Mode: mt.ModeProofGen, + DisableLeafHashing: true, + }, + prevOutputs, + ) + require.NoError(t, err) + + tree, output, err := tries.PackOutputIntoMultiPayloadAndProof( + outputs, + 3, + frame, + previousTree, + ) + require.NoError(t, err) + require.NotNil(t, tree) + require.NotEmpty(t, output) + require.Len(t, output, 3) +}