public MerkleNode(MerkleNode left, MerkleNode right) { Left = left; Right = right; if(left != null) left.Parent = this; if(right != null) right.Parent = this; UpdateHash(); }
public static MerkleNode GetRoot(IEnumerable<uint256> leafs) { var row = leafs.Select(l => new MerkleNode(l)).ToList(); if(row.Count == 0) return new MerkleNode(uint256.Zero); while(row.Count != 1) { var parentRow = new List<MerkleNode>(); for(int i = 0 ; i < row.Count ; i += 2) { var left = row[i]; var right = i + 1 < row.Count ? row[i + 1] : null; var parent = new MerkleNode(left, right); parentRow.Add(parent); } row = parentRow; } return row[0]; }
public MerkleNode GetMerkleRoot() { return(MerkleNode.GetRoot(Transactions.Select(t => t.GetHash()))); }
public MerkleNode GetMerkleRoot() { return(MerkleNode.GetRoot(_graphs.Select(t => t.GetHash()).Prepend(_poaHeader.GetHash()))); }
public static MnemonicReference Parse (ChainBase chain, Wordlist wordList, string sentence, Transaction transaction, MerkleBlock merkleBlock) { var indices = wordList.ToIndices(sentence); //Step1: Determine w = number of words in the mnemonic code int w = indices.Length; //Convert mnemonic code into finalAddress following BIP-0039 var finalAddress = Wordlist.ToBits(indices); var rawAddress = DecryptFinalAddress(finalAddress); int blockHeight = 0; var x = DecodeBlockHeight(rawAddress, out blockHeight); var header = chain.GetBlock((int)blockHeight); if (header == null) { throw new InvalidBrainAddressException("This block does not exists"); } if (header.HashBlock != merkleBlock.Header.GetHash()) { throw new InvalidBrainAddressException("The provided merkleblock do not match the block of the sentence"); } var blockId = header.HashBlock; MerkleNode root = merkleBlock.PartialMerkleTree.TryGetMerkleRoot(); if (root == null || root.Hash != header.Header.HashMerkleRoot) { throw new InvalidBrainAddressException("Invalid partial merkle tree"); } int y1 = BitCount((int)merkleBlock.PartialMerkleTree.TransactionCount); int y2 = 11 * w - 1 - x - c; int y = Math.Min(y1, y2); int txIndex = Decode(Substring(rawAddress, x, y)); var txLeaf = root.GetLeafs().Skip((int)txIndex).FirstOrDefault(); if (txLeaf == null || txLeaf.Hash != transaction.GetHash()) { throw new InvalidBrainAddressException("The transaction do not appear in the block"); } int z1 = BitCount(transaction.Outputs.Count); int z2 = 11 * w - 1 - x - y - c; int z = Math.Min(z1, z2); int outputIndex = Decode(Substring(rawAddress, x + y, z)); if (outputIndex >= transaction.Outputs.Count) { throw new InvalidBrainAddressException("The specified txout index is outside of the transaction bounds"); } var txOut = transaction.Outputs[outputIndex]; var cs = 11 * w - 1 - x - y - z; var actualChecksum = Substring(rawAddress, x + y + z, cs); var expectedChecksum = CalculateChecksum(blockId, txIndex, outputIndex, txOut.ScriptPubKey, cs); if (!actualChecksum.OfType <bool>().SequenceEqual(expectedChecksum.OfType <bool>())) { throw new InvalidBrainAddressException("Invalid checksum"); } return(new MnemonicReference() { BlockHeight = (int)blockHeight, TransactionIndex = (int)txIndex, WordIndices = indices, Checksum = actualChecksum, Output = transaction.Outputs[outputIndex], OutputIndex = (int)outputIndex, BlockId = blockId, Transaction = transaction }); }
public IEnumerable<MerkleNode> EnumerateDescendants() { IEnumerable<MerkleNode> result = new MerkleNode[] { this }; if(Right != null) result = Right.EnumerateDescendants().Concat(result); if(Left != null) result = Left.EnumerateDescendants().Concat(result); return result; }
private static void MarkNodes(MerkleNode root, bool[] vMatch) { BitReader matches = new BitReader(new BitArray(vMatch)); foreach(var leaf in root.GetLeafs()) { if(matches.Read()) { MarkToTop(leaf, true); } } }
private IEnumerable<uint256> GetMatchedTransactionsCore(MerkleNode node, BitReader flags, IEnumerator<uint256> hashes, bool calculateHash) { if(node == null) return new uint256[0]; node.IsMarked = flags.Read(); if(node.IsLeaf || !node.IsMarked) { hashes.MoveNext(); node.Hash = hashes.Current; } if(!node.IsMarked) return new uint256[0]; if(node.IsLeaf) return new uint256[] { node.Hash }; var left = GetMatchedTransactionsCore(node.Left, flags, hashes, calculateHash); var right = GetMatchedTransactionsCore(node.Right, flags, hashes, calculateHash); if(calculateHash) node.UpdateHash(); return left.Concat(right); }
private void BuildCore(MerkleNode node, BitWriter flags) { if(node == null) return; flags.Write(node.IsMarked); if(node.IsLeaf || !node.IsMarked) Hashes.Add(node.Hash); if(node.IsMarked) { BuildCore(node.Left, flags); BuildCore(node.Right, flags); } }
private static void MarkToTop(MerkleNode leaf, bool value) { leaf.IsMarked = value; foreach(var ancestor in leaf.Ancestors()) { ancestor.IsMarked = value; } }