func visitChildren(node data.Hashable, db storage.DB, ops *RadixOperations, depth uint8, action RadixAction) error { inner, ok := node.(*data.InnerNode) if !ok { return nil } return inner.Each(func(pos int, h data.Hash256) error { child, err := db.Get(h) if err != nil { return nil } ops.Add(child, action, h, depth) return visitChildren(child, db, ops, depth+1, action) }) }
func diff(left, right data.Hash256, db storage.DB, ops *RadixOperations, depth uint8) error { var l, r data.Hashable var err error switch { case left.IsZero() && right.IsZero(): return nil case left.IsZero(): r, err = db.Get(left) if err != nil { return err } ops.Add(r, Addition, right, depth) return visitChildren(r, db, ops, depth+1, Deletion) case right.IsZero(): l, err = db.Get(left) if err != nil { return err } ops.Add(l, Addition, left, depth) return visitChildren(l, db, ops, depth+1, Addition) } l, err = db.Get(left) if err != nil { return err } r, err = db.Get(left) if err != nil { return err } ops.Add(r, Addition, right, depth) ops.Add(l, Addition, left, depth) leftInner, leftOk := l.(*data.InnerNode) rightInner, rightOk := r.(*data.InnerNode) switch { case !leftOk && !rightOk: return nil case !leftOk: return visitChildren(r, db, ops, depth+1, Deletion) case !rightOk: return visitChildren(l, db, ops, depth+1, Addition) default: for i := 0; i < 16; i++ { leftChild, rightChild := leftInner.Children[i], rightInner.Children[i] switch { case leftChild == rightChild: continue case leftChild.IsZero(): child, err := db.Get(rightChild) if err != nil { return err } if err := visitChildren(child, db, ops, depth+1, Deletion); err != nil { return err } case rightChild.IsZero(): child, err := db.Get(leftChild) if err != nil { return err } if err := visitChildren(child, db, ops, depth+1, Addition); err != nil { return err } default: if err := diff(leftChild, rightChild, db, ops, depth+1); err != nil { return err } } } } return nil }