internal PSBT(BitcoinStream stream, Network network) { Network = network; Inputs = new PSBTInputList(); Outputs = new PSBTOutputList(); var magicBytes = stream.Inner.ReadBytes(PSBT_MAGIC_BYTES.Length); if (!magicBytes.SequenceEqual(PSBT_MAGIC_BYTES)) { throw new FormatException("Invalid PSBT magic bytes"); } // It will be reassigned in `ReadWriteAsVarString` so no worry to assign 0 length array here. byte[] k = new byte[0]; byte[] v = new byte[0]; var txFound = false; stream.ReadWriteAsVarString(ref k); while (k.Length != 0) { switch (k[0]) { case PSBTConstants.PSBT_GLOBAL_UNSIGNED_TX: if (k.Length != 1) { throw new FormatException("Invalid PSBT. Contains illegal value in key global tx"); } if (tx != null) { throw new FormatException("Duplicate Key, unsigned tx already provided"); } tx = stream.ConsensusFactory.CreateTransaction(); uint size = 0; stream.ReadWriteAsVarInt(ref size); var pos = stream.Counter.ReadenBytes; tx.ReadWrite(stream); if (stream.Counter.ReadenBytes - pos != size) { throw new FormatException("Malformed global tx. Unexpected size."); } if (tx.Inputs.Any(txin => txin.ScriptSig != Script.Empty || txin.WitScript != WitScript.Empty)) { throw new FormatException("Malformed global tx. It should not contain any scriptsig or witness by itself"); } txFound = true; break; case PSBTConstants.PSBT_GLOBAL_XPUB when XPubVersionBytes != null: if (k.Length != 1 + XPubVersionBytes.Length + 74) { throw new FormatException("Malformed global xpub."); } for (int ii = 0; ii < XPubVersionBytes.Length; ii++) { if (k[1 + ii] != XPubVersionBytes[ii]) { throw new FormatException("Malformed global xpub."); } } stream.ReadWriteAsVarString(ref v); KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); var rootedKeyPath = new RootedKeyPath(new HDFingerprint(v.Take(4).ToArray()), path); GlobalXPubs.Add(new ExtPubKey(k, 1 + XPubVersionBytes.Length, 74).GetWif(Network), rootedKeyPath); break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput, duplicate key for unknown value"); } stream.ReadWriteAsVarString(ref v); unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } if (!txFound) { throw new FormatException("Invalid PSBT. No global TX"); } int i = 0; while (stream.Inner.CanRead && i < tx.Inputs.Count) { var psbtin = new PSBTInput(stream, this, (uint)i, tx.Inputs[i]); Inputs.Add(psbtin); i++; } if (i != tx.Inputs.Count) { throw new FormatException("Invalid PSBT. Number of input does not match to the global tx"); } i = 0; while (stream.Inner.CanRead && i < tx.Outputs.Count) { var psbtout = new PSBTOutput(stream, this, (uint)i, tx.Outputs[i]); Outputs.Add(psbtout); i++; } if (i != tx.Outputs.Count) { throw new FormatException("Invalid PSBT. Number of outputs does not match to the global tx"); } }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref this.blocks); }
public void ReadWrite(BitcoinStream s) { s.ReadWrite(ref this.federationId); }
internal PSBT(BitcoinStream stream) { Inputs = new PSBTInputList(); Outputs = new PSBTOutputList(); var magicBytes = stream.Inner.ReadBytes(PSBT_MAGIC_BYTES.Length); if (!magicBytes.SequenceEqual(PSBT_MAGIC_BYTES)) { throw new FormatException("Invalid PSBT magic bytes"); } // It will be reassigned in `ReadWriteAsVarString` so no worry to assign 0 length array here. byte[] k = new byte[0]; byte[] v = new byte[0]; var txFound = false; stream.ReadWriteAsVarString(ref k); while (k.Length != 0) { switch (k.First()) { case PSBTConstants.PSBT_GLOBAL_UNSIGNED_TX: if (k.Length != 1) { throw new FormatException("Invalid PSBT. Contains illegal value in key global tx"); } if (tx != null) { throw new FormatException("Duplicate Key, unsigned tx already provided"); } tx = stream.ConsensusFactory.CreateTransaction(); uint size = 0; stream.ReadWriteAsVarInt(ref size); var pos = stream.Counter.ReadenBytes; tx.ReadWrite(stream); if (stream.Counter.ReadenBytes - pos != size) { throw new FormatException("Malformed global tx. Unexpected size."); } if (tx.Inputs.Any(txin => txin.ScriptSig != Script.Empty || txin.WitScript != WitScript.Empty)) { throw new FormatException("Malformed global tx. It should not contain any scriptsig or witness by itself"); } txFound = true; break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput, duplicate key for unknown value"); } stream.ReadWriteAsVarString(ref v); unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } if (!txFound) { throw new FormatException("Invalid PSBT. No global TX"); } int i = 0; while (stream.Inner.CanRead && i < tx.Inputs.Count) { var psbtin = new PSBTInput(stream, this, (uint)i, tx.Inputs[i]); Inputs.Add(psbtin); i++; } if (i != tx.Inputs.Count) { throw new FormatException("Invalid PSBT. Number of input does not match to the global tx"); } i = 0; while (stream.Inner.CanRead && i < tx.Outputs.Count) { var psbtout = new PSBTOutput(stream, this, (uint)i, tx.Outputs[i]); Outputs.Add(psbtout); i++; } if (i != tx.Outputs.Count) { throw new FormatException("Invalid PSBT. Number of outputs does not match to the global tx"); } AssertSanity(); }
public void Serialize(BitcoinStream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } // Write the utxo // If there is a non-witness utxo, then don't serialize the witness one. if (witness_utxo != null) { // key stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_WITNESS_UTXO; stream.ReadWrite(ref key); // value var data = witness_utxo.ToBytes(); stream.ReadWriteAsVarString(ref data); } if (non_witness_utxo != null) { // key stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_NON_WITNESS_UTXO; stream.ReadWrite(ref key); // value byte[] data = non_witness_utxo.ToBytes(); stream.ReadWriteAsVarString(ref data); } // Write the sighash type if (sighash_type > 0) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_SIGHASH; stream.ReadWrite(ref key); var tmp = Utils.ToBytes((uint)sighash_type, true); stream.ReadWriteAsVarString(ref tmp); } // Write the redeem script if (redeem_script != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_REDEEMSCRIPT; stream.ReadWrite(ref key); var value = redeem_script.ToBytes(); stream.ReadWriteAsVarString(ref value); } // Write the witness script if (witness_script != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_WITNESSSCRIPT; stream.ReadWrite(ref key); var value = witness_script.ToBytes(); stream.ReadWriteAsVarString(ref value); } // Write any partial signatures foreach (var sig_pair in partial_sigs) { var key = new byte[] { PSBTConstants.PSBT_IN_PARTIAL_SIG }.Concat(sig_pair.Key.ToBytes()); stream.ReadWriteAsVarString(ref key); var sig = sig_pair.Value.ToBytes(); stream.ReadWriteAsVarString(ref sig); } // Write any hd keypaths foreach (var pathPair in hd_keypaths) { var key = new byte[] { PSBTConstants.PSBT_IN_BIP32_DERIVATION }.Concat(pathPair.Key.ToBytes()); stream.ReadWriteAsVarString(ref key); var masterFingerPrint = pathPair.Value.MasterFingerprint; var path = pathPair.Value.KeyPath.ToBytes(); var pathInfo = masterFingerPrint.ToBytes().Concat(path); stream.ReadWriteAsVarString(ref pathInfo); } // Write script sig if (final_script_sig != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_SCRIPTSIG; stream.ReadWrite(ref key); byte[] value = final_script_sig.ToBytes(); stream.ReadWriteAsVarString(ref value); } // write script witness if (final_script_witness != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_SCRIPTWITNESS; stream.ReadWrite(ref key); var stack = final_script_witness.ToBytes(); stream.ReadWriteAsVarString(ref stack); } // Write unknown things foreach (var entry in unknown) { var k = entry.Key; var v = entry.Value; stream.ReadWriteAsVarString(ref k); stream.ReadWriteAsVarString(ref v); } var sep = PSBTConstants.PSBT_SEPARATOR; stream.ReadWrite(ref sep); }
internal byte[] ReadData(Stream stream) { uint len = 0; BitcoinStream bitStream = new BitcoinStream(stream, false); if (Code == 0) { return(new byte[0]); } if ((byte)OpcodeType.OP_1 <= (byte)Code && (byte)Code <= (byte)OpcodeType.OP_16) { return(new byte[] { (byte)(Code - OpcodeType.OP_1 + 1) }); } if (Code == OpcodeType.OP_1NEGATE) { return(new byte[] { 0x81 }); } try { if (0x01 <= (byte)Code && (byte)Code <= 0x4b) { len = (uint)Code; } else if (Code == OpcodeType.OP_PUSHDATA1) { len = bitStream.ReadWrite((byte)0); } else if (Code == OpcodeType.OP_PUSHDATA2) { len = bitStream.ReadWrite((ushort)0); } else if (Code == OpcodeType.OP_PUSHDATA4) { len = bitStream.ReadWrite((uint)0); } else { IsInvalid = true; return(new byte[0]); } byte[] data = null; if (len <= MAX_SCRIPT_ELEMENT_SIZE) //Most of the time { data = new byte[len]; var readen = stream.Read(data, 0, data.Length); if (readen != data.Length) { IsInvalid = true; return(new byte[0]); } } else //Mitigate against a big array allocation { List <byte> bytes = new List <byte>(); for (int i = 0; i < len; i++) { var b = stream.ReadByte(); if (b < 0) { IsInvalid = true; return(new byte[0]); } bytes.Add((byte)b); } data = bytes.ToArray(); } return(data); } catch (EndOfStreamException) { IsInvalid = true; return(new byte[0]); } }
internal static byte[] ReadData(Op op, Stream stream, bool ignoreWrongPush = false) { var opcode = op.Code; uint len = 0; BitcoinStream bitStream = new BitcoinStream(stream, false); if (opcode == 0) { return(new byte[0]); } if ((byte)OpcodeType.OP_1 <= (byte)opcode && (byte)opcode <= (byte)OpcodeType.OP_16) { return(new byte[] { (byte)(opcode - OpcodeType.OP_1 + 1) }); } if (opcode == OpcodeType.OP_1NEGATE) { return(new byte[] { 0x81 }); } try { if (0x01 <= (byte)opcode && (byte)opcode <= 0x4b) { len = (uint)opcode; } else if (opcode == OpcodeType.OP_PUSHDATA1) { len = bitStream.ReadWrite((byte)0); } else if (opcode == OpcodeType.OP_PUSHDATA2) { len = bitStream.ReadWrite((ushort)0); } else if (opcode == OpcodeType.OP_PUSHDATA4) { len = bitStream.ReadWrite((uint)0); } else { throw new FormatException("Invalid opcode for pushing data : " + opcode); } } catch (EndOfStreamException) { if (!ignoreWrongPush) { throw new FormatException("Incomplete script"); } op.IncompleteData = true; return(new byte[0]); } if (stream.CanSeek && stream.Length - stream.Position < len) { len = (uint)(stream.Length - stream.Position); if (!ignoreWrongPush) { throw new FormatException("Not enough bytes pushed with " + opcode.ToString() + " expected " + len + " but got " + len); } op.IncompleteData = true; } byte[] data = new byte[len]; var readen = stream.Read(data, 0, data.Length); if (readen != data.Length && !ignoreWrongPush) { throw new FormatException("Not enough bytes pushed with " + opcode.ToString() + " expected " + len + " but got " + readen); } else if (readen != data.Length) { op.IncompleteData = true; Array.Resize(ref data, readen); } return(data); }
public void Load(BitcoinStream stream) { Load(stream, null); }
public void WriteTo(BitcoinStream stream) { WriteTo(stream, null); }
//IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref hash); stream.ReadWrite(ref n); }
//https://en.bitcoin.it/wiki/OP_CHECKSIG public uint256 SignatureHash(Transaction txTo, int nIn, SigHash nHashType) { if (nIn >= txTo.Inputs.Count) { Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n"); return(uint256.One); } // Check for invalid use of SIGHASH_SINGLE if (nHashType == SigHash.Single) { if (nIn >= txTo.Outputs.Count) { Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n"); return(uint256.One); } } var scriptCopy = new Script(_Script); scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR); var txCopy = new Transaction(txTo.ToBytes()); //Set all TxIn script to empty string foreach (var txin in txCopy.Inputs) { txin.ScriptSig = new Script(); } //Copy subscript into the txin script you are checking txCopy.Inputs[nIn].ScriptSig = scriptCopy; var hashType = nHashType & (SigHash)31; if (hashType == SigHash.None) { //The output of txCopy is set to a vector of zero size. txCopy.Outputs.Clear(); //All other inputs aside from the current input in txCopy have their nSequence index set to zero foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } else if (hashType == SigHash.Single) { //The output of txCopy is resized to the size of the current input index+1. txCopy.Outputs.RemoveRange(nIn + 1, txCopy.Outputs.Count - (nIn + 1)); //All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1. for (var i = 0; i < txCopy.Outputs.Count; i++) { if (i == nIn) { continue; } txCopy.Outputs[i] = new TxOut(); } //All other txCopy inputs aside from the current input are set to have an nSequence index of zero. foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } if ((nHashType & SigHash.AnyoneCanPay) != 0) { //The txCopy input vector is resized to a length of one. var script = txCopy.Inputs[nIn]; txCopy.Inputs.Clear(); txCopy.Inputs.Add(script); //The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector. txCopy.Inputs[0].ScriptSig = scriptCopy; } //Serialize TxCopy, append 4 byte hashtypecode var ms = new MemoryStream(); var bitcoinStream = new BitcoinStream(ms, true); txCopy.ReadWrite(bitcoinStream); bitcoinStream.ReadWrite((uint)nHashType); var hashed = ms.ToArray(); return(Hashes.Hash256(hashed)); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref value); stream.ReadWrite(ref publicKey); _MoneyValue = null; //Might been updated }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref prevout); stream.ReadWrite(ref scriptSig); stream.ReadWrite(ref nSequence); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWriteAsVarString(ref _Script); }
//https://en.bitcoin.it/wiki/OP_CHECKSIG public static uint256 SignatureHash(Script scriptCode, Transaction txTo, int nIn, SigHash nHashType, Money amount, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData) { if ((nHashType & SigHash.ForkId) != 0) { nHashType = (SigHash)((int)nHashType & 0x1f); if (amount == null) { throw new ArgumentException("The amount of the output being signed must be provided", "amount"); } uint256 hashPrevouts = uint256.Zero; uint256 hashSequence = uint256.Zero; uint256 hashOutputs = uint256.Zero; if ((nHashType & SigHash.AnyoneCanPay) == 0) { hashPrevouts = precomputedTransactionData == null? GetHashPrevouts(txTo) : precomputedTransactionData.HashPrevouts; } if ((nHashType & SigHash.AnyoneCanPay) == 0 && ((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None) { hashSequence = precomputedTransactionData == null? GetHashSequence(txTo) : precomputedTransactionData.HashSequence; } if (((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None) { hashOutputs = precomputedTransactionData == null? GetHashOutputs(txTo) : precomputedTransactionData.HashOutputs; } else if (((uint)nHashType & 0x1f) == (uint)SigHash.Single && nIn < txTo.Outputs.Count) { BitcoinStream ss = CreateHashWriter(sigversion); ss.ReadWrite(txTo.Outputs[nIn]); hashOutputs = GetHash(ss); } BitcoinStream sss = CreateHashWriter(sigversion); // Version sss.ReadWrite(txTo.Version); // Input prevouts/nSequence (none/all, depending on flags) sss.ReadWrite(hashPrevouts); sss.ReadWrite(hashSequence); // The input being signed (replacing the scriptSig with scriptCode + amount) // The prevout may already be contained in hashPrevout, and the nSequence // may already be contain in hashSequence. sss.ReadWrite(txTo.Inputs[nIn].PrevOut); sss.ReadWrite(scriptCode); sss.ReadWrite(amount.Satoshi); sss.ReadWrite((uint)txTo.Inputs[nIn].Sequence); // Outputs (none/one/all, depending on flags) sss.ReadWrite(hashOutputs); // Locktime sss.ReadWriteStruct(txTo.LockTime); // Sighash type sss.ReadWrite((uint)nHashType | (uint)SigHash.ForkId); return(GetHash(sss)); } if (nIn >= txTo.Inputs.Count) { Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n"); return(uint256.One); } // Check for invalid use of SIGHASH_SINGLE if (nHashType == SigHash.Single) { if (nIn >= txTo.Outputs.Count) { Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n"); return(uint256.One); } } var scriptCopy = new Script(scriptCode._Script); scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR); var txCopy = new Transaction(txTo.ToBytes()); //Set all TxIn script to empty string foreach (var txin in txCopy.Inputs) { txin.ScriptSig = new Script(); } //Copy subscript into the txin script you are checking txCopy.Inputs[nIn].ScriptSig = scriptCopy; var hashType = nHashType & (SigHash)31; if (hashType == SigHash.None) { //The output of txCopy is set to a vector of zero size. txCopy.Outputs.Clear(); //All other inputs aside from the current input in txCopy have their nSequence index set to zero foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } else if (hashType == SigHash.Single) { //The output of txCopy is resized to the size of the current input index+1. txCopy.Outputs.RemoveRange(nIn + 1, txCopy.Outputs.Count - (nIn + 1)); //All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1. for (var i = 0; i < txCopy.Outputs.Count; i++) { if (i == nIn) { continue; } txCopy.Outputs[i] = new TxOut(); } //All other txCopy inputs aside from the current input are set to have an nSequence index of zero. foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } if ((nHashType & SigHash.AnyoneCanPay) != 0) { //The txCopy input vector is resized to a length of one. var script = txCopy.Inputs[nIn]; txCopy.Inputs.Clear(); txCopy.Inputs.Add(script); //The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector. txCopy.Inputs[0].ScriptSig = scriptCopy; } //Serialize TxCopy, append 4 byte hashtypecode var stream = CreateHashWriter(sigversion); txCopy.ReadWrite(stream); stream.ReadWrite((uint)nHashType); return(GetHash(stream)); }
private static uint256 GetHash(BitcoinStream stream) { var preimage = ((MemoryStream)stream.Inner).ToArrayEfficient(); return(Hashes.Hash256(preimage)); }
internal PSBTOutput(BitcoinStream stream, PSBT parent, uint index, TxOut txOut) : base(parent) { if (txOut == null) { throw new ArgumentNullException(nameof(txOut)); } if (parent == null) { throw new ArgumentNullException(nameof(parent)); } TxOut = txOut; Index = index; byte[] k = new byte[0]; byte[] v = new byte[0]; try { stream.ReadWriteAsVarString(ref k); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTOutput. Could not read key", e); } while (k.Length != 0) { try { stream.ReadWriteAsVarString(ref v); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTOutput. Could not read value", e); } switch (k.First()) { case PSBTConstants.PSBT_OUT_REDEEMSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTOutput. Contains illegal value in key for redeem script"); } if (redeem_script != null) { throw new FormatException("Invalid PSBTOutput, duplicate key for redeem_script"); } redeem_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_OUT_WITNESSSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTOutput. Contains illegal value in key for witness script"); } if (witness_script != null) { throw new FormatException("Invalid PSBTOutput, duplicate key for redeem_script"); } witness_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_OUT_BIP32_DERIVATION: var pubkey2 = new PubKey(k.Skip(1).ToArray()); if (hd_keypaths.ContainsKey(pubkey2)) { throw new FormatException("Invalid PSBTOutput, duplicate key for hd_keypaths"); } KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); hd_keypaths.Add(pubkey2, new RootedKeyPath(new HDFingerprint(v.Take(4).ToArray()), path)); break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput, duplicate key for unknown value"); } unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } }
public void CopyParameters(BitcoinStream stream) { ProtocolVersion = stream.ProtocolVersion; IsBigEndian = stream.IsBigEndian; MaxArraySize = stream.MaxArraySize; }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref header); stream.ReadWrite(ref _PartialMerkleTree); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref vprevout); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref vHave); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref vtxundo); }
internal PSBTInput(BitcoinStream stream, PSBT parent, uint index, TxIn input) : base(parent) { TxIn = input; Index = index; originalScriptSig = TxIn.ScriptSig ?? Script.Empty; originalWitScript = TxIn.WitScript ?? WitScript.Empty; byte[] k = new byte[0]; byte[] v = new byte[0]; try { stream.ReadWriteAsVarString(ref k); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTInput. Failed to Parse key.", e); } while (k.Length != 0) { try { stream.ReadWriteAsVarString(ref v); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTInput. Failed to parse key.", e); } switch (k.First()) { case PSBTConstants.PSBT_IN_NON_WITNESS_UTXO: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for NonWitnessUTXO"); } if (non_witness_utxo != null) { throw new FormatException("Invalid PSBTInput. Duplicate non_witness_utxo"); } non_witness_utxo = this.GetConsensusFactory().CreateTransaction(); non_witness_utxo.FromBytes(v); break; case PSBTConstants.PSBT_IN_WITNESS_UTXO: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for WitnessUTXO"); } if (witness_utxo != null) { throw new FormatException("Invalid PSBTInput. Duplicate witness_utxo"); } if (this.GetConsensusFactory().TryCreateNew <TxOut>(out var txout)) { witness_utxo = txout; } else { witness_utxo = new TxOut(); } witness_utxo.FromBytes(v); break; case PSBTConstants.PSBT_IN_PARTIAL_SIG: var pubkey = new PubKey(k.Skip(1).ToArray()); if (partial_sigs.ContainsKey(pubkey)) { throw new FormatException("Invalid PSBTInput. Duplicate key for partial_sigs"); } partial_sigs.Add(pubkey, new TransactionSignature(v)); break; case PSBTConstants.PSBT_IN_SIGHASH: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for SigHash type"); } if (!(sighash_type is null)) { throw new FormatException("Invalid PSBTInput. Duplicate key for sighash_type"); } if (v.Length != 4) { throw new FormatException("Invalid PSBTInput. SigHash Type is not 4 byte"); } var value = Utils.ToUInt32(v, 0, true); if (!Enum.IsDefined(typeof(SigHash), value)) { throw new FormatException($"Invalid PSBTInput Unknown SigHash Type {value}"); } sighash_type = (SigHash)value; break; case PSBTConstants.PSBT_IN_REDEEMSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for redeem script"); } if (redeem_script != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for redeem_script"); } redeem_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_WITNESSSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for witness script"); } if (witness_script != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for redeem_script"); } witness_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_BIP32_DERIVATION: var pubkey2 = new PubKey(k.Skip(1).ToArray()); if (hd_keypaths.ContainsKey(pubkey2)) { throw new FormatException("Invalid PSBTInput. Duplicate key for hd_keypaths"); } var masterFingerPrint = new HDFingerprint(v.Take(4).ToArray()); KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); hd_keypaths.Add(pubkey2, new RootedKeyPath(masterFingerPrint, path)); break; case PSBTConstants.PSBT_IN_SCRIPTSIG: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for final scriptsig"); } if (final_script_sig != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for final_script_sig"); } final_script_sig = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_SCRIPTWITNESS: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for final script witness"); } if (final_script_witness != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for final_script_witness"); } final_script_witness = new WitScript(v); break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput. Duplicate key for unknown value"); } unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } }
public virtual void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref this.header); stream.ReadWrite(ref this.transactions); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref header); stream.ReadWrite(ref vtx); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref this._value); }