Exemplo n.º 1
0
        // IBlockTxesStorage.TryGetTransaction
        private void TestTryGetTransaction(ITestStorageProvider provider)
        {
            using (var storageManager = provider.OpenStorageManager())
            {
                var blockTxesStorage = storageManager.BlockTxesStorage;

                // create a block
                var block = CreateFakeBlock();

                // add block transactions
                blockTxesStorage.TryAddBlockTransactions(block.Hash, block.BlockTxes);

                // verify missing transactions
                BlockTx transaction;
                Assert.IsFalse(blockTxesStorage.TryGetTransaction(UInt256.Zero, 0, out transaction));
                Assert.IsFalse(blockTxesStorage.TryGetTransaction(block.Hash, -1, out transaction));
                Assert.IsFalse(blockTxesStorage.TryGetTransaction(block.Hash, block.Transactions.Length, out transaction));

                // verify transactions
                for (var txIndex = 0; txIndex < block.Transactions.Length; txIndex++)
                {
                    Assert.IsTrue(blockTxesStorage.TryGetTransaction(block.Hash, txIndex, out transaction));
                    Assert.AreEqual(block.Transactions[txIndex].Hash, transaction.Hash);
                    Assert.AreEqual(transaction.Hash, new UInt256(SHA256Static.ComputeDoubleHash(transaction.TxBytes.ToArray())));
                }
            }
        }
Exemplo n.º 2
0
        // IBlockTxesStorage.ReadBlockTransactions
        private void TestReadBlockTransactions(ITestStorageProvider provider)
        {
            using (var storageManager = provider.OpenStorageManager())
            {
                var blockTxesStorage = storageManager.BlockTxesStorage;

                // create a block
                var expectedBlock         = CreateFakeBlock();
                var expectedBlockTxHashes = expectedBlock.Transactions.Select(x => x.Hash).ToList();

                // add block transactions
                blockTxesStorage.TryAddBlockTransactions(expectedBlock.Hash, expectedBlock.BlockTxes);

                // retrieve block transactions
                IEnumerator <BlockTx> rawActualBlockTxes;
                Assert.IsTrue(blockTxesStorage.TryReadBlockTransactions(expectedBlock.Hash, out rawActualBlockTxes));
                var actualBlockTxes     = rawActualBlockTxes.UsingAsEnumerable().ToList();
                var actualBlockTxHashes = actualBlockTxes.Select(x => x.Hash).ToList();

                // verify all retrieved transactions match their hashes
                Assert.IsTrue(actualBlockTxes.All(x => x.Hash == new UInt256(SHA256Static.ComputeDoubleHash(x.TxBytes.ToArray()))));

                // verify retrieved block transactions match stored block transactions
                CollectionAssert.AreEqual(expectedBlockTxHashes, actualBlockTxHashes);
            }
        }
Exemplo n.º 3
0
        public void TestUInt256Sha256()
        {
            var expected = SHA256Static.ComputeDoubleHash(UInt256.ParseHex(TestData.HEX_STRING_64).ToByteArray());
            var actual   = new UInt256(expected).ToByteArray();

            CollectionAssert.AreEqual(expected, actual);
        }
Exemplo n.º 4
0
        public bool VerifySignature(byte[] scriptPubKey, Transaction tx, byte[] sig, byte[] pubKey, int inputIndex, out byte hashType, out byte[] txSignature, out byte[] txSignatureHash)
        {
            // get the 1-byte hashType off the end of sig
            hashType = sig[sig.Length - 1];

            // get the DER encoded portion of sig, which is everything except the last byte (the last byte being hashType)
            var sigDER = sig.Take(sig.Length - 1).ToArray();

            // get the simplified/signing version of the transaction
            txSignature = TxSignature(scriptPubKey, tx, inputIndex, hashType);

            // get the hash of the simplified/signing version of the transaction
            txSignatureHash = SHA256Static.ComputeDoubleHash(txSignature);

            if (this.ignoreSignatures)
            {
                return(true);
            }
            else
            {
#if SECP256K1_DLL
                // verify that signature is valid for pubKey and the simplified/signing transaction's hash
                return(Signatures.Verify(txSignatureHash, sigDER, pubKey) == Signatures.VerifyResult.Verified);
#else
                return(true);
#endif
            }
        }
Exemplo n.º 5
0
        public static T Pair <T>(T left, T right)
            where T : IMerkleTreeNode <T>
        {
            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(left.AsPruned(left.Index, left.Depth + 1, pairHash));
        }
Exemplo n.º 6
0
        public static UInt256 PairHashes(UInt256 left, UInt256 right)
        {
            var bytes = new byte[64];

            left.ToByteArray(bytes, 0);
            right.ToByteArray(bytes, 32);
            return(new UInt256(SHA256Static.ComputeDoubleHash(bytes)));
        }
Exemplo n.º 7
0
        public PublicKeyHashAddress(ImmutableArray <byte> publicKeyHashBytes)
        {
            this.publicKeyHashBytes = publicKeyHashBytes;

            var outputScript = new PayToPublicKeyHashBuilder().CreateOutputFromPublicKeyHash(publicKeyHashBytes.ToArray());

            this.outputScriptHash = new UInt256(SHA256Static.ComputeHash(outputScript));
        }
Exemplo n.º 8
0
        private UInt256 AddressToOutputScriptHash(string address)
        {
            var addressBytes  = Base58Encoding.DecodeWithCheckSum(address);
            var publicKeyHash = addressBytes.Skip(1).ToArray();

            var outputScript     = new PayToPublicKeyHashBuilder().CreateOutputFromPublicKeyHash(publicKeyHash);
            var outputScriptHash = new UInt256(SHA256Static.ComputeHash(outputScript));

            return(outputScriptHash);
        }
Exemplo n.º 9
0
        private UInt256 PublicKeyHashToOutputScriptHash(byte[] publicKeyHash)
        {
            if (publicKeyHash.Length != 20)
            {
                throw new ArgumentException("publicKeyHash");
            }

            var outputScript     = new PayToPublicKeyHashBuilder().CreateOutputFromPublicKeyHash(publicKeyHash);
            var outputScriptHash = new UInt256(SHA256Static.ComputeHash(outputScript));

            return(outputScriptHash);
        }
Exemplo n.º 10
0
        public BlockHeader MineBlockHeader(BlockHeader blockHeader, UInt256 hashTarget)
        {
            var blockHeaderBytes = DataEncoder.EncodeBlockHeader(blockHeader);

            var hashTargetBytes = hashTarget.ToByteArray();

            var start      = 0;
            var finish     = UInt32.MaxValue;
            var total      = 0L;
            var nonceIndex = 76;
            var minedNonce = (UInt32?)null;

            var stopwatch = Stopwatch.StartNew();

            Parallel.For(
                start, finish,
                () => new LocalMinerState(blockHeaderBytes),
                (nonceLong, loopState, localState) =>
            {
                localState.total++;

                var nonce      = (UInt32)nonceLong;
                var nonceBytes = Bits.GetBytes(nonce);
                Buffer.BlockCopy(nonceBytes, 0, localState.headerBytes, nonceIndex, 4);

                var headerBytes = localState.headerBytes;
                var hashBytes   = SHA256Static.ComputeDoubleHash(headerBytes);

                if (BytesCompareLE(hashBytes, hashTargetBytes) < 0)
                {
                    minedNonce = nonce;
                    loopState.Stop();
                }

                return(localState);
            },
                localState => { Interlocked.Add(ref total, localState.total); });

            stopwatch.Stop();

            var hashRate = total / stopwatch.Elapsed.TotalSeconds;

            if (minedNonce == null)
            {
                throw new InvalidOperationException();
            }

            var minedHeader = blockHeader.With(Nonce: minedNonce);

            logger.Debug($"Found block in {stopwatch.Elapsed.TotalMilliseconds:N3}ms at Nonce {minedNonce}, Hash Rate: {hashRate / 1.MILLION()} mHash/s, Total Hash Attempts: {total:N0}, Found Hash: {minedHeader.Hash}");
            return(minedHeader);
        }
Exemplo n.º 11
0
        private static byte[] GetCheckSum(byte[] data)
        {
            //Contract.Requires<ArgumentNullException>(data != null);
            //Contract.Ensures(Contract.Result<byte[]>() != null);

            byte[] hash1 = SHA256Static.ComputeHash(data);
            byte[] hash2 = SHA256Static.ComputeHash(hash1);

            var result = new byte[CheckSumSizeInBytes];

            Buffer.BlockCopy(hash2, 0, result, 0, result.Length);

            return(result);
        }
Exemplo n.º 12
0
        public static BlockHeader DecodeBlockHeader(UInt256 blockHash, byte[] buffer, ref int offset)
        {
            var initialOffset = offset;

            var version       = DecodeUInt32(buffer, ref offset);
            var previousBlock = DecodeUInt256(buffer, ref offset);
            var merkleRoot    = DecodeUInt256(buffer, ref offset);
            var time          = DateTimeOffset.FromUnixTimeSeconds(DecodeUInt32(buffer, ref offset));
            var bits          = DecodeUInt32(buffer, ref offset);
            var nonce         = DecodeUInt32(buffer, ref offset);

            blockHash = blockHash ?? new UInt256(SHA256Static.ComputeDoubleHash(buffer, initialOffset, 80));

            return(new BlockHeader(version, previousBlock, merkleRoot, time, bits, nonce, blockHash));
        }
Exemplo n.º 13
0
        public static UInt256 ComputeHash(IChainState chainState)
        {
            using (var sha256 = new SHA256Managed())
            {
                // add each unspent tx to hash
                foreach (var unspentTx in chainState.ReadUnspentTransactions())
                {
                    var unspentTxBytes = DataEncoder.EncodeUnspentTx(unspentTx);
                    sha256.TransformBlock(unspentTxBytes, 0, unspentTxBytes.Length, unspentTxBytes, 0);
                }
                // finalize hash
                sha256.TransformFinalBlock(new byte[0], 0, 0);

                // hash again to return double-hashed utxo committment
                return(new UInt256(SHA256Static.ComputeHash(sha256.Hash)));
            }
        }
Exemplo n.º 14
0
        public static DecodedTx EncodeTransaction(UInt32 Version, ImmutableArray <TxInput> Inputs, ImmutableArray <TxOutput> Outputs, UInt32 LockTime)
        {
            using (var stream = new MemoryStream())
                using (var writer = new BinaryWriter(stream))
                {
                    writer.WriteUInt32(Version);
                    writer.WriteList(Inputs, input => EncodeTxInput(writer, input));
                    writer.WriteList(Outputs, output => EncodeTxOutput(writer, output));
                    writer.WriteUInt32(LockTime);

                    var txBytes = stream.ToArray();
                    var txHash  = new UInt256(SHA256Static.ComputeDoubleHash(txBytes));
                    var tx      = new Transaction(Version, Inputs, Outputs, LockTime, txHash);

                    return(new DecodedTx(txBytes.ToImmutableArray(), tx));
                }
        }
Exemplo n.º 15
0
        public byte[] CreatePublicKeyScript(byte[] publicKey)
        {
            var publicKeyHash = RIPEMD160Static.ComputeHash(SHA256Static.ComputeHash(publicKey));

            using (var publicKeyScript = new ScriptBuilder())
            {
                publicKeyScript.WriteOp(ScriptOp.OP_DUP);
                publicKeyScript.WriteOp(ScriptOp.OP_HASH160);
                publicKeyScript.WritePushData(publicKeyHash);
                publicKeyScript.WriteOp(ScriptOp.OP_EQUALVERIFY);
                publicKeyScript.WriteOp(ScriptOp.OP_CHECKSIG);

                //Debug.WriteLine("Public Script: {0}".Format2(publicKeyScript.GetScript().ToHexDataString()));

                return(publicKeyScript.GetScript());
            }
        }
Exemplo n.º 16
0
        private async Task ScanBlock(ICoreStorage coreStorage, IChainState chainState, ChainedHeader scanBlock, bool forward, CancellationToken cancelToken = default(CancellationToken))
        {
            var replayTxes = BlockReplayer.ReplayBlock(coreStorage, chainState, scanBlock.Hash, forward, cancelToken);

            var txScanner = new ActionBlock <ValidatableTx>(
                validatableTx =>
            {
                var tx      = validatableTx.Transaction;
                var txIndex = validatableTx.Index;

                if (!validatableTx.IsCoinbase)
                {
                    for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++)
                    {
                        var input                = tx.Inputs[inputIndex];
                        var prevOutput           = validatableTx.PrevTxOutputs[inputIndex];
                        var prevOutputScriptHash = new UInt256(SHA256Static.ComputeHash(prevOutput.ScriptPublicKey));

                        var chainPosition = ChainPosition.Fake();
                        var entryType     = forward ? EnumWalletEntryType.Spend : EnumWalletEntryType.UnSpend;

                        ScanForEntry(chainPosition, entryType, (TxOutput)prevOutput, prevOutputScriptHash);
                    }
                }

                for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++)
                {
                    var output           = tx.Outputs[outputIndex];
                    var outputScriptHash = new UInt256(SHA256Static.ComputeHash(output.ScriptPublicKey));

                    var chainPosition = ChainPosition.Fake();
                    var entryType     =
                        validatableTx.IsCoinbase ?
                        (forward ? EnumWalletEntryType.Mine : EnumWalletEntryType.UnMine)
                                : (forward ? EnumWalletEntryType.Receive : EnumWalletEntryType.UnReceieve);

                    ScanForEntry(chainPosition, entryType, output, outputScriptHash);
                }
            });

            replayTxes.LinkTo(txScanner, new DataflowLinkOptions {
                PropagateCompletion = true
            });
            await txScanner.Completion;
        }
Exemplo n.º 17
0
        public byte[] CreatePrivateKeyScript(Transaction tx, int inputIndex, byte hashType, ECPrivateKeyParameters privateKey, ECPublicKeyParameters publicKey)
        {
            //TODO
            var scriptEngine = new ScriptEngine();

            var publicAddress   = CreatePublicAddress(publicKey);
            var publicKeyScript = CreatePublicKeyScript(publicAddress);
            var txSignature     = scriptEngine.TxSignature(publicKeyScript, tx, inputIndex, hashType);
            var txSignatureHash = SHA256Static.ComputeDoubleHash(txSignature);

            //Debug.WriteLine("Signing Tx:       {0}".Format2(txSignature.ToHexDataString()));
            //Debug.WriteLine("Signing Tx  Hash: {0}".Format2(txSignatureHash.ToHexDataString()));

            var signer = new ECDsaSigner();

            signer.Init(forSigning: true, parameters: privateKey);
            var signature = signer.GenerateSignature(txSignatureHash);
            var r         = signature[0];
            var s         = signature[1];

            byte[] sigEncoded;
            using (var stream = new MemoryStream())
            {
                using (var asn1Stream = new Asn1OutputStream(stream))
                {
                    asn1Stream.WriteObject(new DerSequence(new DerInteger(r), new DerInteger(s)));
                }

                sigEncoded = stream.ToArray().Concat(hashType);
            }

            //Debug.WriteLine("Sig R:       {0}".Format2(r.ToHexNumberStringUnsigned()));
            //Debug.WriteLine("Sig S:       {0}".Format2(s.ToHexNumberStringUnsigned()));
            //Debug.WriteLine("Sig Encoded: {0}".Format2(sigEncoded.ToHexDataString()));

            using (var privateKeyScript = new ScriptBuilder())
            {
                privateKeyScript.WritePushData(sigEncoded);
                privateKeyScript.WritePushData(publicAddress);
                //Debug.WriteLine("Private Script: {0}".Format2(privateKeyScript.GetScript().ToHexDataString()));

                return(privateKeyScript.GetScript());
            }
        }
Exemplo n.º 18
0
        public static Transaction DecodeTransaction(UInt256 txHash, byte[] buffer, ref int offset)
        {
            var initialOffset = offset;

            // read version
            var version = DecodeUInt32(buffer, ref offset);

            // read inputs
            var inputs = DecodeTxInputList(buffer, ref offset);

            // read outputs
            var outputs = DecodeTxOutputList(buffer, ref offset);

            // read lockTime
            var lockTime = DecodeUInt32(buffer, ref offset);

            txHash = txHash ?? new UInt256(SHA256Static.ComputeDoubleHash(buffer, initialOffset, offset - initialOffset));

            return(new Transaction(version, inputs, outputs, lockTime, txHash));
        }
Exemplo n.º 19
0
        public void ReplayBlockExample()
        {
            // create example core daemon
            BlockProvider embeddedBlocks; IStorageManager storageManager;

            using (var coreDaemon = CreateExampleDaemon(out embeddedBlocks, out storageManager, maxHeight: 999))
                using (embeddedBlocks)
                    using (storageManager)
                    {
                        // start a chain at the genesis block to represent the processed progress
                        var processedChain = Chain.CreateForGenesisBlock(coreDaemon.ChainParams.GenesisChainedHeader).ToBuilder();

                        // a dictionary of public key script hashes can be created for any addresses of interest, allowing for quick checking
                        var scriptHashesOfInterest = new HashSet <UInt256>();

                        // retrieve a chainstate to replay blocks with
                        using (var chainState = coreDaemon.GetChainState())
                        {
                            // enumerate the steps needed to take the currently processed chain towards the current chainstate
                            foreach (var pathElement in processedChain.NavigateTowards(chainState.Chain))
                            {
                                // retrieve the next block to replay and whether to replay forwards, or backwards for a re-org
                                var replayForward = pathElement.Item1 > 0;
                                var replayBlock   = pathElement.Item2;

                                // begin replaying the transactions in the replay block
                                // if this is a re-org, the transactions will be replayed in reverse block order
                                var replayTxes = BlockReplayer.ReplayBlock(coreDaemon.CoreStorage, chainState, replayBlock.Hash, replayForward);

                                // prepare the tx scanner
                                var txScanner = new ActionBlock <ValidatableTx>(
                                    validatableTx =>
                                {
                                    // the transaction being replayed
                                    var tx = validatableTx.Transaction;

                                    // the previous tx outputs for each of the replay transaction's inputs
                                    var prevTxOutputs = validatableTx.PrevTxOutputs;

                                    // scan the replay transaction's inputs
                                    if (!validatableTx.IsCoinbase)
                                    {
                                        for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++)
                                        {
                                            var input             = tx.Inputs[inputIndex];
                                            var inputPrevTxOutput = validatableTx.PrevTxOutputs[inputIndex];

                                            // check if the input's previous transaction output is of interest
                                            var inputPrevTxOutputPublicScriptHash = new UInt256(SHA256Static.ComputeHash(inputPrevTxOutput.ScriptPublicKey));
                                            if (scriptHashesOfInterest.Contains(inputPrevTxOutputPublicScriptHash))
                                            {
                                                if (replayForward)
                                                { /* An output for an address of interest is being spent. */
                                                }
                                                else
                                                { /* An output for an address of interest is being "unspent", on re-org. */
                                                }
                                            }
                                        }
                                    }

                                    // scan the replay transaction's outputs
                                    for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++)
                                    {
                                        var output = tx.Outputs[outputIndex];

                                        // check if the output is of interest
                                        var outputPublicScriptHash = new UInt256(SHA256Static.ComputeHash(output.ScriptPublicKey));
                                        if (scriptHashesOfInterest.Contains(outputPublicScriptHash))
                                        {
                                            if (replayForward)
                                            { /* An output for an address of interest is being minted. */
                                            }
                                            else
                                            { /* An output for an address of interest is being "unminted", on re-org. */
                                            }
                                        }
                                    }
                                });

                                // hook up and wait for the tx scanner
                                replayTxes.LinkTo(txScanner, new DataflowLinkOptions {
                                    PropagateCompletion = true
                                });
                                txScanner.Completion.Wait();

                                // a wallet would now commit its progress

                                /*
                                 * walletDatabase.CurrentBlock = replayBlock.Hash;
                                 * walletDatabase.Commit();
                                 */

                                // TODO: after successfully committing, a wallet would notify CoreDaemon of its current progress
                                // TODO: CoreDaemon will use this information in order to determine how far in the current chainstate it is safe to prune
                                // TODO: with this in place, if a wallet suffers a failure to commit it can just replay the block
                                // TODO: wallets can also remain disconnected from CoreDaemon, and just replay blocks to catch up when they are reconnected

                                // update the processed chain so that the next step towards the current chainstate can be taken
                                if (replayForward)
                                {
                                    processedChain.AddBlock(replayBlock);
                                }
                                else
                                {
                                    processedChain.RemoveBlock(replayBlock);
                                }
                            }
                        }

                        logger.Info("Processed chain height: {0:N0}", processedChain.Height);
                    }
        }
Exemplo n.º 20
0
 public static UInt256 CalculateBlockHash(UInt32 Version, UInt256 PreviousBlock, UInt256 MerkleRoot, DateTimeOffset Time, UInt32 Bits, UInt32 Nonce)
 {
     return(new UInt256(SHA256Static.ComputeDoubleHash(DataEncoder.EncodeBlockHeader(Version, PreviousBlock, MerkleRoot, Time, Bits, Nonce))));
 }
Exemplo n.º 21
0
 public static UInt32 CalculatePayloadChecksum(byte[] payload)
 {
     return(Bits.ToUInt32(SHA256Static.ComputeDoubleHash(payload)));
 }
Exemplo n.º 22
0
        private bool ExecuteOps(byte[] scriptPubKey, Transaction tx, int inputIndex, byte[] script, out Stack stack, out Stack altStack)
        {
            stack    = new Stack();
            altStack = new Stack();

            using (var scriptStream = new MemoryStream(script))
                using (var opReader = new BinaryReader(scriptStream))
                {
                    while (opReader.BaseStream.Position < script.Length)
                    {
                        var opByte = opReader.ReadByte();
                        var op     = (ScriptOp)Enum.ToObject(typeof(ScriptOp), opByte);

                        if (logger.IsTraceEnabled)
                        {
                            logger.Trace("Executing {0} with stack count: {1}", OpName(opByte), stack.Count);
                        }

                        switch (op)
                        {
                        // Constants
                        case ScriptOp.OP_PUSHDATA1:
                        {
                            if (opReader.BaseStream.Position + 1 >= script.Length)
                            {
                                return(false);
                            }

                            var length = opReader.ReadByte();
                            stack.PushBytes(opReader.ReadExactly(length));
                        }
                        break;

                        case ScriptOp.OP_PUSHDATA2:
                        {
                            if (opReader.BaseStream.Position + 2 >= script.Length)
                            {
                                return(false);
                            }

                            var length = opReader.ReadUInt16();
                            stack.PushBytes(opReader.ReadExactly(length));
                        }
                        break;

                        case ScriptOp.OP_PUSHDATA4:
                        {
                            if (opReader.BaseStream.Position + 4 >= script.Length)
                            {
                                return(false);
                            }

                            var length = opReader.ReadUInt32();
                            stack.PushBytes(opReader.ReadExactly(length.ToIntChecked()));
                        }
                        break;

                        // Flow control
                        case ScriptOp.OP_NOP:
                        {
                        }
                        break;

                        // Stack
                        case ScriptOp.OP_DROP:
                        {
                            if (stack.Count < 1)
                            {
                                return(false);
                            }

                            var value = stack.PopBytes();

                            if (logger.IsTraceEnabled)
                            {
                                logger.Trace("{0} dropped {1}", OpName(opByte), value);
                            }
                        }
                        break;

                        case ScriptOp.OP_DUP:
                        {
                            if (stack.Count < 1)
                            {
                                return(false);
                            }

                            var value = stack.PeekBytes();
                            stack.PushBytes(value);

                            if (logger.IsTraceEnabled)
                            {
                                logger.Trace("{0} duplicated {2}", OpName(opByte), value);
                            }
                        }
                        break;

                        // Splice

                        // Bitwise logic
                        case ScriptOp.OP_EQUAL:
                        case ScriptOp.OP_EQUALVERIFY:
                        {
                            if (stack.Count < 2)
                            {
                                return(false);
                            }

                            var value1 = stack.PopBytes();
                            var value2 = stack.PopBytes();

                            var result = value1.SequenceEqual(value2);
                            stack.PushBool(result);

                            if (logger.IsTraceEnabled)
                            {
                                logger.Trace(
                                    @"{0} compared values:
    value1: {1}
    value2: {2}
    result: {3}", OpName(opByte), value1, value2, result);
                            }

                            if (op == ScriptOp.OP_EQUALVERIFY)
                            {
                                if (result)
                                {
                                    stack.PopBool();
                                }
                                else
                                {
                                    return(false);
                                }
                            }
                        }
                        break;

                        // Arithmetic
                        // Note: Arithmetic inputs are limited to signed 32-bit integers, but may overflow their output.

                        // Crypto
                        case ScriptOp.OP_SHA256:
                        {
                            if (stack.Count < 1)
                            {
                                return(false);
                            }

                            var value = stack.PopBytes().ToArray();

                            var hash = SHA256Static.ComputeHash(value);
                            stack.PushBytes(hash);

                            if (logger.IsTraceEnabled)
                            {
                                logger.Trace(
                                    @"{0} hashed value:
    value:  {1}
    hash:   {2}", OpName(opByte), value, hash);
                            }
                        }
                        break;

                        case ScriptOp.OP_HASH160:
                        {
                            if (stack.Count < 1)
                            {
                                return(false);
                            }

                            var value = stack.PopBytes().ToArray();

                            var hash = RIPEMD160Static.ComputeHash(SHA256Static.ComputeHash(value));
                            stack.PushBytes(hash);

                            if (logger.IsTraceEnabled)
                            {
                                logger.Trace(
                                    @"{0} hashed value:
    value:  {1}
    hash:   {2}", OpName(opByte), value, hash);
                            }
                        }
                        break;

                        case ScriptOp.OP_CHECKSIG:
                        case ScriptOp.OP_CHECKSIGVERIFY:
                        {
                            if (stack.Count < 2)
                            {
                                return(false);
                            }

                            var pubKey = stack.PopBytes().ToArray();
                            var sig    = stack.PopBytes().ToArray();

                            var startTime = DateTime.UtcNow;

                            byte hashType; byte[] txSignature, txSignatureHash;
                            var  result = VerifySignature(scriptPubKey, tx, sig, pubKey, inputIndex, out hashType, out txSignature, out txSignatureHash);
                            stack.PushBool(result);

                            var finishTime = DateTime.UtcNow;

                            if (logger.IsTraceEnabled)
                            {
                                logger.Trace(
                                    @"{0} executed in {9} ms:
    tx:                 {1}
    inputIndex:         {2}
    pubKey:             {3}
    sig:                {4}
    hashType:           {5}
    txSignature:        {6}
    txSignatureHash:    {7}
    result:             {8}", OpName(opByte), new byte[0] /*tx.ToRawBytes()*/, inputIndex, pubKey, sig, hashType, txSignature, txSignatureHash, result, (finishTime - startTime).TotalMilliseconds.ToString("0"));
                            }

                            if (op == ScriptOp.OP_CHECKSIGVERIFY)
                            {
                                if (result)
                                {
                                    stack.PopBool();
                                }
                                else
                                {
                                    return(false);
                                }
                            }
                        }
                        break;

                        // Pseudo-words
                        // These words are used internally for assisting with transaction matching. They are invalid if used in actual scripts.

                        // Reserved words
                        // Any opcode not assigned is also reserved. Using an unassigned opcode makes the transaction invalid.

                        default:
                            //OP_PUSHBYTES1-75
                            if (opByte >= (int)ScriptOp.OP_PUSHBYTES1 && opByte <= (int)ScriptOp.OP_PUSHBYTES75)
                            {
                                stack.PushBytes(opReader.ReadExactly(opByte));

                                if (logger.IsTraceEnabled)
                                {
                                    logger.Trace("{0} loaded {1} bytes onto the stack: {2}", OpName(opByte), opByte, stack.PeekBytes());
                                }
                            }
                            // Unknown op
                            else
                            {
                                var message = $"Invalid operation in tx {tx.Hash} input {inputIndex}: {new[] { opByte }.ToHexNumberString()} {OpName(opByte)}";
                                //logger.Warn(message);
                                throw new Exception(message);
                            }
                            break;
                        }

                        if (logger.IsTraceEnabled)
                        {
                            logger.Trace(new string('-', 80));
                        }
                    }
                }

            // TODO verify no if/else blocks left over

            // TODO not entirely sure what default return should be
            return(true);
        }
Exemplo n.º 23
0
        public byte[] CreateOutputFromPublicKey(byte[] publicKey)
        {
            var publicKeyHash = RIPEMD160Static.ComputeHash(SHA256Static.ComputeHash(publicKey));

            return(CreateOutputFromPublicKeyHash(publicKeyHash));
        }
Exemplo n.º 24
0
 public static UInt256 CalculateBlockHash(BlockHeader blockHeader)
 {
     return(new UInt256(SHA256Static.ComputeDoubleHash(DataEncoder.EncodeBlockHeader(blockHeader))));
 }