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))); }
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); }