Example #1
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
			};
		}
Example #2
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
            });
        }
Example #3
0
		public static MnemonicReference Create
			(ChainBase chain,
			Transaction transaction,
			MerkleBlock merkleBlock,
			int txOutIndex)
		{
			var blockId = merkleBlock.Header.GetHash();
			var merkleRoot = merkleBlock.PartialMerkleTree.TryGetMerkleRoot();
			if(merkleRoot == null || merkleRoot.Hash != merkleBlock.Header.HashMerkleRoot)
				throw new InvalidBrainAddressException("Invalid merkle block");
			if(txOutIndex >= transaction.Outputs.Count)
				throw new InvalidBrainAddressException("The specified txout index is outside of the transaction bounds");
			var matchedLeaf = merkleRoot.GetLeafs().Select((node, index) => new
			{
				node,
				index
			}).FirstOrDefault(_ => _.node.Hash == transaction.GetHash());
			if(matchedLeaf == null)
				throw new InvalidBrainAddressException("Transaction not included in this merkle block");

			var chainedHeader = chain.GetBlock(blockId);
			if(chainedHeader == null)
				throw new InvalidBrainAddressException("The block provided is not in the current chain");
			var blockHeight = chainedHeader.Height;
			var txIndex = matchedLeaf.index;
			var txOut = transaction.Outputs[txOutIndex];
			var block = chain.GetBlock(blockId);


			BitArray encodedBlockHeight = EncodeBlockHeight(blockHeight);
			int x = encodedBlockHeight.Length;

			//ymin = ceiling(log(txIndex + 1, 2))
			int ymin = BitCount(txIndex + 1);
			//zmin = ceiling(log(outputIndex + 1, 2))
			int zmin = BitCount(txOutIndex + 1);

			//w = ceiling((x + ymin + zmin + c + 1)/11)
			int w = RoundTo(x + ymin + zmin + c + 1, 11) / 11;
			int y = 0;
			int z = 0;
			for( ; ; w++)
			{
				int y1 = BitCount((int)merkleBlock.PartialMerkleTree.TransactionCount);
				int y2 = 11 * w - 1 - x - c;
				y = Math.Min(y1, y2);
				if(ymin > y)
					continue;
				int z1 = BitCount(transaction.Outputs.Count);
				int z2 = 11 * w - 1 - x - y - c;
				z = Math.Min(z1, z2);
				if(zmin > z)
					continue;
				break;
			}

			var cs = 11 * w - 1 - x - y - z;
			var checksum = CalculateChecksum(blockId, txIndex, txOutIndex, txOut.ScriptPubKey, cs);

			var rawAddress = Concat(encodedBlockHeight, Encode(txIndex, y), Encode(txOutIndex, z), checksum);

			var finalAddress = EncryptRawAddress(rawAddress);

			return new MnemonicReference()
			{
				BlockHeight = blockHeight,
				TransactionIndex = txIndex,
				OutputIndex = txOutIndex,
				Checksum = checksum,
				WordIndices = Wordlist.ToIntegers(finalAddress),
				Output = transaction.Outputs[txOutIndex],
				Transaction = transaction,
				BlockId = blockId
			};
		}
Example #4
0
        public static MnemonicReference Create
            (ChainBase chain,
            Transaction transaction,
            MerkleBlock merkleBlock,
            int txOutIndex)
        {
            var blockId    = merkleBlock.Header.GetHash();
            var merkleRoot = merkleBlock.PartialMerkleTree.TryGetMerkleRoot();

            if (merkleRoot == null || merkleRoot.Hash != merkleBlock.Header.HashMerkleRoot)
            {
                throw new InvalidBrainAddressException("Invalid merkle block");
            }
            if (txOutIndex >= transaction.Outputs.Count)
            {
                throw new InvalidBrainAddressException("The specified txout index is outside of the transaction bounds");
            }
            var matchedLeaf = merkleRoot.GetLeafs().Select((node, index) => new
            {
                node,
                index
            }).FirstOrDefault(_ => _.node.Hash == transaction.GetHash());

            if (matchedLeaf == null)
            {
                throw new InvalidBrainAddressException("Transaction not included in this merkle block");
            }

            var chainedHeader = chain.GetBlock(blockId);

            if (chainedHeader == null)
            {
                throw new InvalidBrainAddressException("The block provided is not in the current chain");
            }
            var blockHeight = chainedHeader.Height;
            var txIndex     = matchedLeaf.index;
            var txOut       = transaction.Outputs[txOutIndex];
            var block       = chain.GetBlock(blockId);


            BitArray encodedBlockHeight = EncodeBlockHeight(blockHeight);
            int      x = encodedBlockHeight.Length;

            //ymin = ceiling(log(txIndex + 1, 2))
            int ymin = BitCount(txIndex + 1);
            //zmin = ceiling(log(outputIndex + 1, 2))
            int zmin = BitCount(txOutIndex + 1);

            //w = ceiling((x + ymin + zmin + c + 1)/11)
            int w = RoundTo(x + ymin + zmin + c + 1, 11) / 11;
            int y = 0;
            int z = 0;

            for ( ; ; w++)
            {
                int y1 = BitCount((int)merkleBlock.PartialMerkleTree.TransactionCount);
                int y2 = 11 * w - 1 - x - c;
                y = Math.Min(y1, y2);
                if (ymin > y)
                {
                    continue;
                }
                int z1 = BitCount(transaction.Outputs.Count);
                int z2 = 11 * w - 1 - x - y - c;
                z = Math.Min(z1, z2);
                if (zmin > z)
                {
                    continue;
                }
                break;
            }

            var cs       = 11 * w - 1 - x - y - z;
            var checksum = CalculateChecksum(blockId, txIndex, txOutIndex, txOut.ScriptPubKey, cs);

            var rawAddress = Concat(encodedBlockHeight, Encode(txIndex, y), Encode(txOutIndex, z), checksum);

            var finalAddress = EncryptRawAddress(rawAddress);

            return(new MnemonicReference()
            {
                BlockHeight = blockHeight,
                TransactionIndex = txIndex,
                OutputIndex = txOutIndex,
                Checksum = checksum,
                WordIndices = Wordlist.ToIntegers(finalAddress),
                Output = transaction.Outputs[txOutIndex],
                Transaction = transaction,
                BlockId = blockId
            });
        }