/// <summary> /// Remove superflous branches /// </summary> /// <param name="transaction"></param> /// <returns></returns> public PartialMerkleTree Trim(params uint256[] matchedTransactions) { var trimmed = new PartialMerkleTree(); trimmed.TransactionCount = this.TransactionCount; MerkleNode root = GetMerkleRoot(); foreach (MerkleNode leaf in root.GetLeafs()) { MarkToTop(leaf, false); } var flags = new BitWriter(); foreach (MerkleNode leaf in root.GetLeafs().Where(l => matchedTransactions.Contains(l.Hash))) { MarkToTop(leaf, true); } trimmed.BuildCore(root, flags); trimmed.Flags = flags.ToBitArray(); return(trimmed); }
private static void MarkNodes(MerkleNode root, bool[] vMatch) { var matches = new BitReader(new BitArray(vMatch)); foreach (MerkleNode leaf in root.GetLeafs()) { if (matches.Read()) { MarkToTop(leaf, true); } } }
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 }); }
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); } } }