Ejemplo n.º 1
0
        public void FinishPairing()
        {
            if (this.leftNodes.Count == 0)
                throw new InvalidOperationException();

            while (this.leftNodes.Count > 1)
            {
                var leftNode = this.leftNodes.Last();
                var rightNode = new MerkleTreeNode(leftNode.Index + (1 << leftNode.Depth), leftNode.Depth, leftNode.Hash, pruned: true);
                AddNode(rightNode);
            }
        }
Ejemplo n.º 2
0
        public void TestCalculateMerkleRoot()
        {
            var node1 = new MerkleTreeNode(index: 0, depth: 0, hash: (UInt256)1, pruned: false);
            var node2 = new MerkleTreeNode(index: 1, depth: 0, hash: (UInt256)2, pruned: false);
            var node3 = new MerkleTreeNode(index: 2, depth: 0, hash: (UInt256)3, pruned: false);

            var depth1Hash1 = MerkleTree.PairHashes(node1.Hash, node2.Hash);
            var depth1Hash2 = MerkleTree.PairHashes(node3.Hash, node3.Hash);

            var expectedMerkleRoot = MerkleTree.PairHashes(depth1Hash1, depth1Hash2);

            var hashes = new List<UInt256> { node1.Hash, node2.Hash, node3.Hash };
            var actualMerkleRoot = MerkleTree.CalculateMerkleRoot(hashes); ;

            Assert.AreEqual(expectedMerkleRoot, actualMerkleRoot);
        }
Ejemplo n.º 3
0
        public static MerkleTreeNode Pair(MerkleTreeNode left, MerkleTreeNode right)
        {
            if (left.Depth != right.Depth)
                throw new InvalidOperationException();
            if (!left.Pruned)
                throw new ArgumentException("left");
            if (!right.Pruned)
                throw new ArgumentException("right");

            var expectedIndex = left.Index + (1 << left.Depth);
            if (right.Index != expectedIndex)
                throw new InvalidOperationException();

            var pairHashBytes = new byte[64];
            left.Hash.ToByteArray(pairHashBytes, 0);
            right.Hash.ToByteArray(pairHashBytes, 32);

            var pairHash = new UInt256(SHA256Static.ComputeDoubleHash(pairHashBytes));

            return new MerkleTreeNode(left.Index, left.Depth + 1, pairHash, pruned: true);
        }
Ejemplo n.º 4
0
        public void AddNode(MerkleTreeNode newNode)
        {
            // verify index is as expected
            if (newNode.Index != this.expectedIndex)
                throw new InvalidOperationException();

            // determine the index the next node should be
            this.expectedIndex += 1 << newNode.Depth;

            // when streamining nodes, treat them as being pruned so they can be paired together
            newNode = newNode.AsPruned();

            if (this.leftNodes.Count == 0)
            {
                this.leftNodes.Add(newNode);
            }
            else
            {
                var leftNode = this.leftNodes.Last();

                if (newNode.Depth < leftNode.Depth)
                {
                    this.leftNodes.Add(newNode);
                }
                else if (newNode.Depth == leftNode.Depth)
                {
                    this.leftNodes[this.leftNodes.Count - 1] = leftNode.PairWith(newNode);
                }
                else if (newNode.Depth > leftNode.Depth)
                {
                    throw new InvalidOperationException();
                }

                this.ClosePairs();
            }
        }
Ejemplo n.º 5
0
        public void TestPruneMerkleTreeNodes()
        {
            var node1 = new MerkleTreeNode(index: 0, depth: 0, hash: (UInt256)1, pruned: false);
            var node2 = new MerkleTreeNode(index: 1, depth: 0, hash: (UInt256)2, pruned: false);
            var node3 = new MerkleTreeNode(index: 2, depth: 0, hash: (UInt256)3, pruned: false);
            var node4 = new MerkleTreeNode(index: 3, depth: 0, hash: (UInt256)4, pruned: false);
            var node5 = new MerkleTreeNode(index: 4, depth: 0, hash: (UInt256)5, pruned: false);
            var node6 = new MerkleTreeNode(index: 5, depth: 0, hash: (UInt256)6, pruned: false);
            var node7 = new MerkleTreeNode(index: 6, depth: 0, hash: (UInt256)7, pruned: false);

            var depth1Node1 = node1.AsPruned().PairWith(node2.AsPruned());
            var depth1Node2 = node3.AsPruned().PairWith(node4.AsPruned());
            var depth1Node3 = node5.AsPruned().PairWith(node6.AsPruned());
            var depth1Node4 = node7.AsPruned().PairWithSelf();

            var depth2Node1 = depth1Node1.PairWith(depth1Node2);
            var depth2Node2 = depth1Node3.PairWith(depth1Node4);

            var merkleRoot = depth2Node1.PairWith(depth2Node2);

            var nodes = new List<MerkleTreeNode> { node1, node2, node3, node4, node5, node6, node7 };

            var cursor = new MemoryMerkleTreePruningCursor<MerkleTreeNode>(nodes);

            //////////////////////////////////////////////////

            var expectedNodes1 = nodes;
            var actualNodes1 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes1, actualNodes1);

            //////////////////////////////////////////////////

            MerkleTree.PruneNode(cursor, 2);

            var expectedNodes2 = new List<MerkleTreeNode> { node1, node2, node3.AsPruned(), node4, node5, node6, node7 };
            var actualNodes2 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes2, actualNodes2);

            //////////////////////////////////////////////////

            MerkleTree.PruneNode(cursor, 0);

            var expectedNodes3 = new List<MerkleTreeNode> { node1.AsPruned(), node2, node3.AsPruned(), node4, node5, node6, node7 };
            var actualNodes3 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes3, actualNodes3);

            //////////////////////////////////////////////////

            MerkleTree.PruneNode(cursor, 1);

            var expectedNodes4 = new List<MerkleTreeNode> { depth1Node1, node3.AsPruned(), node4, node5, node6, node7 };
            var actualNodes4 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes4, actualNodes4);

            //////////////////////////////////////////////////

            MerkleTree.PruneNode(cursor, 3);

            var expectedNodes5 = new List<MerkleTreeNode> { depth2Node1, node5, node6, node7 };
            var actualNodes5 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes5, actualNodes5);

            //////////////////////////////////////////////////

            MerkleTree.PruneNode(cursor, 5);

            var expectedNodes6 = new List<MerkleTreeNode> { depth2Node1, node5, node6.AsPruned(), node7 };
            var actualNodes6 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes6, actualNodes6);

            //////////////////////////////////////////////////

            MerkleTree.PruneNode(cursor, 6);

            var expectedNodes8 = new List<MerkleTreeNode> { depth2Node1, node5, node6.AsPruned(), depth1Node4 };
            var actualNodes8 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes8, actualNodes8);

            //////////////////////////////////////////////////

            MerkleTree.PruneNode(cursor, 4);

            var expectedNodes9 = new List<MerkleTreeNode> { merkleRoot };
            var actualNodes9 = cursor.ReadNodes().ToList();
            CollectionAssert.AreEqual(expectedNodes9, actualNodes9);
        }
Ejemplo n.º 6
0
        public void TestReadMerkleTreeNodes()
        {
            var node1 = new MerkleTreeNode(index: 0, depth: 0, hash: (UInt256)1, pruned: false);
            var node2 = new MerkleTreeNode(index: 1, depth: 0, hash: (UInt256)2, pruned: false);
            var node3 = new MerkleTreeNode(index: 2, depth: 0, hash: (UInt256)3, pruned: false);
            var node4 = new MerkleTreeNode(index: 3, depth: 0, hash: (UInt256)4, pruned: false);

            var depth1Hash1 = MerkleTree.PairHashes(node1.Hash, node2.Hash);
            var depth1Hash2 = MerkleTree.PairHashes(node3.Hash, node4.Hash);
            var merkleRoot = MerkleTree.PairHashes(depth1Hash1, depth1Hash2);

            var nodes = new List<MerkleTreeNode> { node1, node2, node3, node4 };

            var actualNodes = MerkleTree.ReadMerkleTreeNodes(merkleRoot, nodes).ToList();

            CollectionAssert.AreEqual(nodes, actualNodes);
        }
        public void WriteNode(MerkleTreeNode node)
        {
            if (!node.Pruned)
                throw new ArgumentException();

            var recordBlockIndexColumn = new Int32ColumnValue { Columnid = cursor.blockIndexColumnId };
            var recordTxIndexColumn = new Int32ColumnValue { Columnid = cursor.txIndexColumnId };
            Api.RetrieveColumns(cursor.jetSession, cursor.blocksTableId, recordBlockIndexColumn, recordTxIndexColumn);

            if (this.blockIndex != recordBlockIndexColumn.Value.Value)
                throw new InvalidOperationException();
            if (node.Index != recordTxIndexColumn.Value.Value)
                throw new InvalidOperationException();

            using (var jetUpdate = cursor.jetSession.BeginUpdate(cursor.blocksTableId, JET_prep.Replace))
            {
                Api.SetColumns(cursor.jetSession, cursor.blocksTableId,
                    new Int32ColumnValue { Columnid = cursor.blockDepthColumnId, Value = node.Depth },
                    new BytesColumnValue { Columnid = cursor.blockTxHashColumnId, Value = DbEncoder.EncodeUInt256(node.Hash) },
                    new Int32ColumnValue { Columnid = cursor.blockTxBytesColumnId, Value = null });

                jetUpdate.Save();
            }
        }
        public void WriteNode(MerkleTreeNode node)
        {
            if (!node.Pruned)
                throw new InvalidOperationException();
            if (this.index < 0 || this.index >= this.nodes.Count)
                throw new InvalidOperationException();

            this.nodes[this.index] = new BlockTx(node.Index, node.Depth, node.Hash, node.Pruned, null);
        }
        public void WriteNode(MerkleTreeNode node)
        {
            if (!node.Pruned)
                throw new ArgumentException();

            var kvPair = cursor.GetCurrent().Value;

            UInt256 recordBlockHash; int txIndex;
            DbEncoder.DecodeBlockHashTxIndex(kvPair.Key, out recordBlockHash, out txIndex);

            if (this.blockHash != recordBlockHash)
                throw new InvalidOperationException();
            if (node.Index != txIndex)
                throw new InvalidOperationException();

            var key = DbEncoder.EncodeBlockHashTxIndex(blockHash, node.Index);
            var blockTx = new BlockTx(node.Index, node.Depth, node.Hash, node.Pruned, null);
            cursor.Put(key, DataEncoder.EncodeBlockTx(blockTx), CursorPutOptions.Current);
        }
Ejemplo n.º 10
0
        public static MerkleTreeNode PairWithSelf(MerkleTreeNode node)
        {
            if (!node.Pruned)
                throw new ArgumentException("left");

            return Pair(node, new MerkleTreeNode(node.Index + (1 << node.Depth), node.Depth, node.Hash, pruned: true));
        }
Ejemplo n.º 11
0
 public MerkleTreeNode PairWith(MerkleTreeNode right)
 {
     return Pair(this, right);
 }
Ejemplo n.º 12
0
 public MerkleTreeNode PairWith(MerkleTreeNode right)
 {
     return(Pair(this, right));
 }