Exemplo n.º 1
0
        public UInt256 ComputeHash(Transaction transaction, int protocolVersion)
        {
            var buffer = new ArrayBufferWriter <byte>();

            _transactionSerializer.Serialize(transaction,
                                             protocolVersion,
                                             buffer,
                                             new ProtocolTypeSerializerOptions((SerializerOptions.SERIALIZE_WITNESS, false)));

            return(HashGenerator.DoubleSha256AsUInt256(buffer.WrittenSpan));
        }
        public UInt256 ComputeHash(BlockHeader header, int protocolVersion)
        {
            var buffer = new ArrayBufferWriter <byte>(80);

            _blockHeaderSerializer.Serialize(header, protocolVersion, buffer);

            //slicing first 80 bytes because the header includes the tx varint value that doesn't need to be included to compute the hash
            return(HashGenerator.DoubleSha256AsUInt256(buffer.WrittenSpan.Slice(0, 80)));
        }
Exemplo n.º 3
0
        private int GetBlockSize(Protocol.Types.Block block)
        {
            var buffer = new PooledByteBufferWriter(block.Transactions !.Length * 256);

            return(_blockSerializer.Serialize(
                       block,
                       KnownVersion.CurrentVersion,
                       new PooledByteBufferWriter(block.Transactions !.Length * 256),
                       new ProtocolTypeSerializerOptions((SerializerOptions.SERIALIZE_WITNESS, false))
                       ));
        }
        public static int WriteArray <TSerializableType>(this IBufferWriter <byte> writer, TSerializableType[]?items, int protocolVersion, IProtocolTypeSerializer <TSerializableType> serializer, ProtocolTypeSerializerOptions?options = null)
        {
            if ((items?.Length ?? 0) == 0)
            {
                return(writer.WriteVarInt(0));
            }

            int size = WriteVarInt(writer, (ulong)items !.Length);

            for (int i = 0; i < items.Length; i++)
            {
                size += serializer.Serialize(items[i], protocolVersion, writer, options);
            }

            return(size);
        }
 public static int WriteWithSerializer <TSerializableType>(this IBufferWriter <byte> writer, TSerializableType item, int protocolVersion, IProtocolTypeSerializer <TSerializableType> serializer, ProtocolTypeSerializerOptions?options = null)
 {
     return(serializer.Serialize(item, protocolVersion, writer, options));
 }
        private bool PerformCheck(Transaction transaction, [MaybeNullWhen(true)] out TransactionValidationState state)
        {
            state = new TransactionValidationState();

            if (transaction.Inputs !.Length == 0)
            {
                return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-vin-empty"));
            }

            if (transaction.Outputs !.Length == 0)
            {
                return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-vout-empty"));
            }

            // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
            int size = _transactionSerializer.Serialize(transaction, KnownVersion.CurrentVersion, new ArrayBufferWriter <byte>(), new ProtocolTypeSerializerOptions((SerializerOptions.SERIALIZE_WITNESS, false)));

            if (size * _consensusParameters.WitnessScaleFactor > _consensusParameters.MaxBlockWeight)
            {
                return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-oversize"));
            }

            // Check for negative or overflow output values (see CVE-2010-5139)
            long totalOutput = 0;

            foreach (TransactionOutput output in transaction.Outputs)
            {
                if (output.Value < 0)
                {
                    return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-vout-negative"));
                }

                if (output.Value > _consensusParameters.MaxMoney)
                {
                    return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-vout-toolarge"));
                }

                totalOutput += output.Value;
                if (totalOutput < 0 || totalOutput > _consensusParameters.MaxMoney)
                {
                    return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-txouttotal-toolarge"));
                }
            }


            // Check for duplicate inputs (see CVE-2018-17144)
            // While Consensus::CheckTxInputs does check if all inputs of a tx are available, and UpdateCoins marks all inputs
            // of a tx as spent, it does not check if the tx has duplicate inputs.
            // Failure to run this check will result in either a crash or an inflation bug, depending on the implementation of
            // the underlying coins database.
            var usedOutPoints = new HashSet <OutPoint>();

            foreach (TransactionInput input in transaction.Inputs)
            {
                if (!usedOutPoints.Add(input.PreviousOutput !))
                {
                    return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-inputs-duplicate"));
                }
            }

            if (transaction.IsCoinBase())
            {
                // ensure coinbase transaction input has a signature script with proper size

                int firstInputScriptSignatureLength = transaction.Inputs[0].SignatureScript !.Length;
                if (firstInputScriptSignatureLength < 2 || firstInputScriptSignatureLength > 100)
                {
                    return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-cb-length"));
                }
            }
            else
            {
                foreach (TransactionInput input in transaction.Inputs)
                {
                    if (input.PreviousOutput !.IsNull())
                    {
                        return(state.Invalid(TransactionValidationStateResults.Consensus, "bad-txns-prevout-null"));
                    }
                }
            }

            return(true);
        }