Пример #1
0
		public MerkleNode(MerkleNode left, MerkleNode right)
		{
			Left = left;
			Right = right;
			if(left != null)
				left.Parent = this;
			if(right != null)
				right.Parent = this;
			UpdateHash();
		}
Пример #2
0
		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];
		}
Пример #3
0
 public MerkleNode GetMerkleRoot()
 {
     return(MerkleNode.GetRoot(Transactions.Select(t => t.GetHash())));
 }
Пример #4
0
 public MerkleNode GetMerkleRoot()
 {
     return(MerkleNode.GetRoot(_graphs.Select(t => t.GetHash()).Prepend(_poaHeader.GetHash())));
 }
Пример #5
0
        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
            });
        }
Пример #6
0
		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;
		}
Пример #7
0
		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);
				}
			}
		}
Пример #8
0
		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);
		}
Пример #9
0
		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);
			}
		}
Пример #10
0
		private static void MarkToTop(MerkleNode leaf, bool value)
		{
			leaf.IsMarked = value;
			foreach(var ancestor in leaf.Ancestors())
			{
				ancestor.IsMarked = value;
			}
		}