diff --git a/node/consensus/data/consensus_frames.go b/node/consensus/data/consensus_frames.go index 873374c..f91fd98 100644 --- a/node/consensus/data/consensus_frames.go +++ b/node/consensus/data/consensus_frames.go @@ -74,6 +74,7 @@ func (e *DataClockConsensusEngine) syncWithMesh() error { func (e *DataClockConsensusEngine) prove( previousFrame *protobufs.ClockFrame, ) (*protobufs.ClockFrame, error) { + time.Sleep(40 * time.Second) if e.lastProven >= previousFrame.FrameNumber && e.lastProven != 0 { return previousFrame, nil } diff --git a/node/consensus/data/message_validators.go b/node/consensus/data/message_validators.go index f06596d..f2eef1c 100644 --- a/node/consensus/data/message_validators.go +++ b/node/consensus/data/message_validators.go @@ -117,7 +117,7 @@ func (e *DataClockConsensusEngine) validateTxMessage(peerID peer.ID, message *pb if err != nil { panic(err) } - if frameNumber+2 < head.FrameNumber { + if frameNumber+1 < head.FrameNumber { return p2p.ValidationResultIgnore } } diff --git a/node/crypto/proof_tree.go b/node/crypto/proof_tree.go index 73d50f4..61780d2 100644 --- a/node/crypto/proof_tree.go +++ b/node/crypto/proof_tree.go @@ -23,7 +23,7 @@ const ( ) type VectorCommitmentNode interface { - Commit() []byte + Commit(recalculate bool) []byte } type VectorCommitmentLeafNode struct { @@ -38,8 +38,8 @@ type VectorCommitmentBranchNode struct { Commitment []byte } -func (n *VectorCommitmentLeafNode) Commit() []byte { - if n.Commitment == nil { +func (n *VectorCommitmentLeafNode) Commit(recalculate bool) []byte { + if n.Commitment == nil || recalculate { h := sha512.New() h.Write([]byte{0}) h.Write(n.Key) @@ -49,12 +49,12 @@ func (n *VectorCommitmentLeafNode) Commit() []byte { return n.Commitment } -func (n *VectorCommitmentBranchNode) Commit() []byte { - if n.Commitment == nil { +func (n *VectorCommitmentBranchNode) Commit(recalculate bool) []byte { + if n.Commitment == nil || recalculate { data := []byte{} for _, child := range n.Children { if child != nil { - out := child.Commit() + out := child.Commit(recalculate) switch c := child.(type) { case *VectorCommitmentBranchNode: h := sha512.New() @@ -84,7 +84,7 @@ func (n *VectorCommitmentBranchNode) Verify(index int, proof []byte) bool { if n.Commitment == nil { for _, child := range n.Children { if child != nil { - out := child.Commit() + out := child.Commit(false) switch c := child.(type) { case *VectorCommitmentBranchNode: h := sha512.New() @@ -108,7 +108,7 @@ func (n *VectorCommitmentBranchNode) Verify(index int, proof []byte) bool { } else { child := n.Children[index] if child != nil { - out := child.Commit() + out := child.Commit(false) switch c := child.(type) { case *VectorCommitmentBranchNode: h := sha512.New() @@ -134,7 +134,7 @@ func (n *VectorCommitmentBranchNode) Prove(index int) []byte { data := []byte{} for _, child := range n.Children { if child != nil { - out := child.Commit() + out := child.Commit(false) switch c := child.(type) { case *VectorCommitmentBranchNode: h := sha512.New() @@ -416,13 +416,14 @@ func (t *VectorCommitmentTree) Delete(key []byte) error { return errors.New("empty key not allowed") } - var delete func(node VectorCommitmentNode, depth int) VectorCommitmentNode - delete = func(node VectorCommitmentNode, depth int) VectorCommitmentNode { + var remove func(node VectorCommitmentNode, depth int) VectorCommitmentNode + remove = func(node VectorCommitmentNode, depth int) VectorCommitmentNode { if node == nil { return nil } switch n := node.(type) { + case *VectorCommitmentLeafNode: if bytes.Equal(n.Key, key) { return nil @@ -430,63 +431,66 @@ func (t *VectorCommitmentTree) Delete(key []byte) error { return n case *VectorCommitmentBranchNode: - // Check prefix match for i, expectedNibble := range n.Prefix { currentNibble := getNextNibble(key, depth+i*BranchBits) if currentNibble != expectedNibble { - return n // Key doesn't match prefix, nothing to delete + return n } } - // Delete at final position after prefix finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits) - n.Children[finalNibble] = delete(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits) + n.Children[finalNibble] = + remove(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits) + n.Commitment = nil - // Count remaining children childCount := 0 var lastChild VectorCommitmentNode - var lastIndex int + var lastChildIndex int for i, child := range n.Children { if child != nil { childCount++ lastChild = child - lastIndex = i + lastChildIndex = i } } - if childCount == 0 { + switch childCount { + case 0: return nil - } else if childCount == 1 { - // If the only child is a leaf, keep structure if its path matches - if leaf, ok := lastChild.(*VectorCommitmentLeafNode); ok { - if lastIndex == getLastNibble(leaf.Key, len(n.Prefix)) { - return n - } - return leaf - } - // If it's a branch, merge the prefixes - if branch, ok := lastChild.(*VectorCommitmentBranchNode); ok { - branch.Prefix = append(n.Prefix, branch.Prefix...) - return branch - } - } - return n - } + case 1: + if childBranch, ok := lastChild.(*VectorCommitmentBranchNode); ok { + // Merge: + // n.Prefix + [lastChildIndex] + childBranch.Prefix + mergedPrefix := make([]int, 0, len(n.Prefix)+1+len(childBranch.Prefix)) + mergedPrefix = append(mergedPrefix, n.Prefix...) + mergedPrefix = append(mergedPrefix, lastChildIndex) + mergedPrefix = append(mergedPrefix, childBranch.Prefix...) - return nil + childBranch.Prefix = mergedPrefix + childBranch.Commitment = nil + return childBranch + } + + return lastChild + default: + return n + } + default: + return node + } } - t.Root = delete(t.Root, 0) + t.Root = remove(t.Root, 0) return nil } // Commit returns the root of the tree -func (t *VectorCommitmentTree) Commit() []byte { +func (t *VectorCommitmentTree) Commit(recalculate bool) []byte { if t.Root == nil { return make([]byte, 64) } - return t.Root.Commit() + return t.Root.Commit(recalculate) } func debugNode(node VectorCommitmentNode, depth int, prefix string) { diff --git a/node/crypto/proof_tree_test.go b/node/crypto/proof_tree_test.go index c7f186b..f855398 100644 --- a/node/crypto/proof_tree_test.go +++ b/node/crypto/proof_tree_test.go @@ -36,7 +36,7 @@ func BenchmarkVectorCommitmentTreeCommit(b *testing.B) { if err != nil { b.Errorf("Failed to insert item %d: %v", i, err) } - tree.Commit() + tree.Commit(false) } } @@ -221,7 +221,7 @@ func TestVectorCommitmentTrees(t *testing.T) { // Root should change after insert tree.Insert([]byte("key1"), []byte("value1")) - firstRoot := tree.Root.Commit() + firstRoot := tree.Root.Commit(false) if bytes.Equal(firstRoot, bytes.Repeat([]byte{0x00}, 64)) { t.Error("Root hash should change after insert") @@ -229,7 +229,7 @@ func TestVectorCommitmentTrees(t *testing.T) { // Root should change after update tree.Insert([]byte("key1"), []byte("value2")) - secondRoot := tree.Root.Commit() + secondRoot := tree.Root.Commit(false) if bytes.Equal(secondRoot, firstRoot) { t.Error("Root hash should change after update") @@ -248,14 +248,27 @@ func TestVectorCommitmentTrees(t *testing.T) { addresses := [][]byte{} - for i := 0; i < 1000; i++ { + for i := 0; i < 10000; i++ { d := make([]byte, 32) rand.Read(d) addresses = append(addresses, d) } - // Insert 1000 items - for i := 0; i < 1000; i++ { + kept := [][]byte{} + for i := 0; i < 5000; i++ { + kept = append(kept, addresses[i]) + } + + newAdditions := [][]byte{} + for i := 0; i < 5000; i++ { + d := make([]byte, 32) + rand.Read(d) + newAdditions = append(newAdditions, d) + kept = append(kept, d) + } + + // Insert 10000 items + for i := 0; i < 10000; i++ { key := addresses[i] value := addresses[i] err := tree.Insert(key, value) @@ -264,8 +277,8 @@ func TestVectorCommitmentTrees(t *testing.T) { } } - // Insert 1000 items in reverse - for i := 999; i >= 0; i-- { + // Insert 10000 items in reverse + for i := 9999; i >= 0; i-- { key := addresses[i] value := addresses[i] err := cmptree.Insert(key, value) @@ -275,7 +288,7 @@ func TestVectorCommitmentTrees(t *testing.T) { } // Verify all items - for i := 0; i < 1000; i++ { + for i := 0; i < 10000; i++ { key := addresses[i] expected := addresses[i] value, err := tree.Get(key) @@ -294,8 +307,44 @@ func TestVectorCommitmentTrees(t *testing.T) { } } - tcommit := tree.Root.Commit() - cmptcommit := cmptree.Root.Commit() + // delete keys + for i := 5000; i < 10000; i++ { + key := addresses[i] + fmt.Printf("delete %x\n", key) + tree.Delete(key) + } + + // add new + for i := 0; i < 5000; i++ { + tree.Insert(newAdditions[i], newAdditions[i]) + } + + cmptree = &VectorCommitmentTree{} + + for i := 0; i < 10000; i++ { + cmptree.Insert(kept[i], kept[i]) + } + // Verify all items + for i := 0; i < 10000; i++ { + key := kept[i] + expected := kept[i] + value, err := tree.Get(key) + if err != nil { + t.Errorf("Failed to get item %d: %v", i, err) + } + cmpvalue, err := cmptree.Get(key) + if err != nil { + t.Errorf("Failed to get item %d: %v", i, err) + } + if !bytes.Equal(value, expected) { + t.Errorf("Item %d: expected %x, got %x", i, string(expected), string(value)) + } + if !bytes.Equal(expected, cmpvalue) { + t.Errorf("Item %d: expected %x, got %x", i, string(value), string(cmpvalue)) + } + } + tcommit := tree.Root.Commit(false) + cmptcommit := cmptree.Root.Commit(false) if !bytes.Equal(tcommit, cmptcommit) { t.Errorf("tree mismatch, %x, %x", tcommit, cmptcommit) diff --git a/node/execution/intrinsics/token/application/token_application.go b/node/execution/intrinsics/token/application/token_application.go index d6e4c54..8424152 100644 --- a/node/execution/intrinsics/token/application/token_application.go +++ b/node/execution/intrinsics/token/application/token_application.go @@ -209,7 +209,7 @@ func (a *TokenApplication) ApplyTransitions( continue } else if len(t.Mint.Proofs) >= 3 && currentFrameNumber > PROOF_FRAME_CUTOFF { frameNumber := binary.BigEndian.Uint64(t.Mint.Proofs[2]) - if frameNumber < currentFrameNumber-2 { + if frameNumber < currentFrameNumber-1 { fails[i] = transition continue } diff --git a/node/execution/intrinsics/token/token_execution_engine.go b/node/execution/intrinsics/token/token_execution_engine.go index f0f35d9..2bafaed 100644 --- a/node/execution/intrinsics/token/token_execution_engine.go +++ b/node/execution/intrinsics/token/token_execution_engine.go @@ -348,7 +348,7 @@ func NewTokenExecutionEngine( e.provingKeyAddress = provingKeyAddress frame, _, err := e.clockStore.GetLatestDataClockFrame(e.intrinsicFilter) - if err != nil || frame.FrameNumber < 184479 { + if err != nil || frame.FrameNumber < 186405 { e.rebuildStateTree() } else { e.stateTree, err = e.clockStore.GetDataStateTree(e.intrinsicFilter) @@ -457,7 +457,7 @@ func (e *TokenExecutionEngine) rebuildStateTree() { e.logger.Info("committing state tree") - root := e.stateTree.Commit() + root := e.stateTree.Commit(true) e.logger.Info( "committed state tree", @@ -1049,7 +1049,7 @@ func (e *TokenExecutionEngine) ProcessFrame( e.logger.Info("committing state tree") - root := stateTree.Commit() + root := stateTree.Commit(false) e.logger.Info( "commited state tree",