mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-28 13:57:26 +08:00
resolve state tree issue, ensure message validation is consistent with mint
This commit is contained in:
parent
a0107caabc
commit
5ed5f4ca6a
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user