@@ -23,156 +23,101 @@ internal PSBTInput(PSBT parent, uint index) : base(parent)
2323 internal PSBTInput ( Map map , PSBT parent , uint index ) : base ( parent )
2424 {
2525 Index = index ;
26- Load ( map ) ;
27- }
28-
29- protected virtual void Load ( Map map )
30- {
31- while ( map . Pop ( out byte [ ] k , out byte [ ] v ) )
26+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_NON_WITNESS_UTXO , out var b ) )
3227 {
33-
34- switch ( k . First ( ) )
28+ non_witness_utxo = Parent . GetConsensusFactory ( ) . CreateTransaction ( ) ;
29+ non_witness_utxo . FromBytes ( b ) ;
30+ }
31+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_WITNESS_UTXO , out b ) )
32+ {
33+ if ( Parent . GetConsensusFactory ( ) . TryCreateNew < TxOut > ( out var txout ) )
3534 {
36- case PSBTConstants . PSBT_IN_NON_WITNESS_UTXO :
37- if ( k . Length != 1 )
38- throw new FormatException (
39- "Invalid PSBTInput. Contains illegal value in key for NonWitnessUTXO" ) ;
40- if ( non_witness_utxo != null )
41- throw new FormatException ( "Invalid PSBTInput. Duplicate non_witness_utxo" ) ;
42- non_witness_utxo = Parent . GetConsensusFactory ( ) . CreateTransaction ( ) ;
43- non_witness_utxo . FromBytes ( v ) ;
44- break ;
45- case PSBTConstants . PSBT_IN_WITNESS_UTXO :
46- if ( k . Length != 1 )
47- throw new FormatException (
48- "Invalid PSBTInput. Contains illegal value in key for WitnessUTXO" ) ;
49- if ( witness_utxo != null )
50- throw new FormatException ( "Invalid PSBTInput. Duplicate witness_utxo" ) ;
51- if ( Parent . GetConsensusFactory ( ) . TryCreateNew < TxOut > ( out var txout ) )
52- {
53- witness_utxo = txout ;
54- }
55- else
56- {
57- witness_utxo = new TxOut ( ) ;
58- }
35+ witness_utxo = txout ;
36+ }
37+ else
38+ {
39+ witness_utxo = new TxOut ( ) ;
40+ }
5941
60- witness_utxo . FromBytes ( v ) ;
61- break ;
62- case PSBTConstants . PSBT_IN_PARTIAL_SIG :
63- var pkbytes = k . Skip ( 1 ) . ToArray ( ) ;
64- if ( pkbytes . Length == 33 )
65- {
66- var pubkey = new PubKey ( pkbytes ) ;
67- if ( partial_sigs . ContainsKey ( pubkey ) )
68- throw new FormatException ( "Invalid PSBTInput. Duplicate key for partial_sigs" ) ;
69- partial_sigs . Add ( pubkey , new TransactionSignature ( v ) ) ;
70- }
71- else
72- throw new FormatException ( "Unexpected public key size in the PSBT" ) ;
73-
74- break ;
75- case PSBTConstants . PSBT_IN_SIGHASH :
76- if ( k . Length != 1 )
77- throw new FormatException (
78- "Invalid PSBTInput. Contains illegal value in key for SigHash type" ) ;
79- if ( ! ( sighash_type is null ) )
80- throw new FormatException ( "Invalid PSBTInput. Duplicate key for sighash_type" ) ;
81- if ( v . Length != 4 )
82- throw new FormatException ( "Invalid PSBTInput. SigHash Type is not 4 byte" ) ;
83- var value = Utils . ToUInt32 ( v , 0 , true ) ;
84- if ( value is not ( 1 or 2 or 3 or 0 or 1 | 0x80 or 2 | 0x80 or 3 | 0x80 or 0 | 0x80 ) )
85- throw new FormatException ( $ "Invalid PSBTInput Unknown SigHash Type { value } ") ;
86- sighash_type = value ;
87- break ;
88- case PSBTConstants . PSBT_IN_REDEEMSCRIPT :
89- if ( k . Length != 1 )
90- throw new FormatException (
91- "Invalid PSBTInput. Contains illegal value in key for redeem script" ) ;
92- if ( redeem_script != null )
93- throw new FormatException ( "Invalid PSBTInput. Duplicate key for redeem_script" ) ;
94- redeem_script = Script . FromBytesUnsafe ( v ) ;
95- break ;
96- case PSBTConstants . PSBT_IN_WITNESSSCRIPT :
97- if ( k . Length != 1 )
98- throw new FormatException (
99- "Invalid PSBTInput. Contains illegal value in key for witness script" ) ;
100- if ( witness_script != null )
101- throw new FormatException ( "Invalid PSBTInput. Duplicate key for redeem_script" ) ;
102- witness_script = Script . FromBytesUnsafe ( v ) ;
103- break ;
104- case PSBTConstants . PSBT_IN_TAP_KEY_SIG :
105- if ( k . Length != 1 )
106- throw new FormatException (
107- "Invalid PSBTInput. Unexpected key length for PSBT_IN_TAP_KEY_SIG" ) ;
108- if ( ! TaprootSignature . TryParse ( v , out var sig ) )
109- throw new FormatException ( "Invalid PSBTInput. Contains invalid TaprootSignature" ) ;
110- TaprootKeySignature = sig ;
111- break ;
112- case PSBTConstants . PSBT_IN_TAP_INTERNAL_KEY :
113- if ( k . Length != 1 )
114- throw new FormatException (
115- "Invalid PSBTInput. Unexpected key length for PSBT_IN_TAP_INTERNAL_KEY" ) ;
116- if ( ! TaprootInternalPubKey . TryCreate ( v , out var tpk ) )
117- throw new FormatException ( "Invalid PSBTInput. Contains invalid internal taproot pubkey" ) ;
118- TaprootInternalKey = tpk ;
119- break ;
120- case PSBTConstants . PSBT_IN_BIP32_DERIVATION :
121- var pubkey2 = new PubKey ( k . Skip ( 1 ) . ToArray ( ) ) ;
122- if ( hd_keypaths . ContainsKey ( pubkey2 ) )
123- throw new FormatException ( "Invalid PSBTInput. Duplicate key for hd_keypaths" ) ;
124- var masterFingerPrint = new HDFingerprint ( v . Take ( 4 ) . ToArray ( ) ) ;
125- KeyPath path = KeyPath . FromBytes ( v . Skip ( 4 ) . ToArray ( ) ) ;
126- hd_keypaths . Add ( pubkey2 , new RootedKeyPath ( masterFingerPrint , path ) ) ;
127- break ;
128- case PSBTConstants . PSBT_IN_TAP_BIP32_DERIVATION :
129- var pubkey3 = new TaprootPubKey ( k . Skip ( 1 ) . ToArray ( ) ) ;
130- if ( hd_taprootkeypaths . ContainsKey ( pubkey3 ) )
131- throw new FormatException (
132- "Invalid PSBTOutput, duplicate key for PSBT_IN_TAP_BIP32_DERIVATION" ) ;
133- var bs = new BitcoinStream ( v ) ;
134- List < uint256 > hashes = null ! ;
135- bs . ReadWrite ( ref hashes ) ;
136- var pos = ( int ) bs . Inner . Position ;
137- KeyPath path2 = KeyPath . FromBytes ( v . Skip ( pos + 4 ) . ToArray ( ) ) ;
138- hd_taprootkeypaths . Add ( pubkey3 ,
139- new TaprootKeyPath (
140- new RootedKeyPath ( new HDFingerprint ( v . Skip ( pos ) . Take ( 4 ) . ToArray ( ) ) , path2 ) ,
141- hashes . ToArray ( ) ) ) ;
142- break ;
143- case PSBTConstants . PSBT_IN_TAP_MERKLE_ROOT :
144- if ( k . Length != 1 )
145- throw new FormatException (
146- "Invalid PSBTInput. Unexpected key length for PSBT_IN_TAP_MERKLE_ROOT" ) ;
147- if ( v . Length != 32 )
148- throw new FormatException (
149- "Invalid PSBTInput. Unexpected value length for PSBT_IN_TAP_MERKLE_ROOT" ) ;
150- TaprootMerkleRoot = new uint256 ( v ) ;
151- break ;
152- case PSBTConstants . PSBT_IN_SCRIPTSIG :
153- if ( k . Length != 1 )
154- throw new FormatException (
155- "Invalid PSBTInput. Contains illegal value in key for final scriptsig" ) ;
156- if ( FinalScriptSig != null )
157- throw new FormatException ( "Invalid PSBTInput. Duplicate key for final_script_sig" ) ;
158- FinalScriptSig = Script . FromBytesUnsafe ( v ) ;
159- break ;
160- case PSBTConstants . PSBT_IN_SCRIPTWITNESS :
161- if ( k . Length != 1 )
162- throw new FormatException (
163- "Invalid PSBTInput. Contains illegal value in key for final script witness" ) ;
164- if ( FinalScriptWitness != null )
165- throw new FormatException ( "Invalid PSBTInput. Duplicate key for final_script_witness" ) ;
166- FinalScriptWitness = new WitScript ( v ) ;
167- break ;
168- default :
169- if ( unknown . ContainsKey ( k ) )
170- throw new FormatException ( "Invalid PSBTInput. Duplicate key for unknown value" ) ;
171- unknown . Add ( k , v ) ;
172- break ;
42+ witness_utxo . FromBytes ( b ) ;
43+ }
44+
45+ foreach ( var kv in map . RemoveAll < byte [ ] > ( PSBTConstants . PSBT_IN_PARTIAL_SIG ) )
46+ {
47+ var pkbytes = kv . Key . Skip ( 1 ) . ToArray ( ) ;
48+ if ( pkbytes . Length == 33 )
49+ {
50+ var pubkey = new PubKey ( pkbytes ) ;
51+ if ( partial_sigs . ContainsKey ( pubkey ) )
52+ throw new FormatException ( "Invalid PSBTInput. Duplicate key for partial_sigs" ) ;
53+ partial_sigs . Add ( pubkey , new TransactionSignature ( kv . Value ) ) ;
17354 }
55+ else
56+ throw new FormatException ( "Unexpected public key size in the PSBT" ) ;
57+ }
17458
59+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_SIGHASH , out b ) )
60+ {
61+ if ( b . Length != 4 )
62+ throw new FormatException ( "Invalid PSBTInput. SigHash Type is not 4 byte" ) ;
63+ var value = Utils . ToUInt32 ( b , 0 , true ) ;
64+ if ( value is not ( 1 or 2 or 3 or 0 or 1 | 0x80 or 2 | 0x80 or 3 | 0x80 or 0 | 0x80 ) )
65+ throw new FormatException ( $ "Invalid PSBTInput Unknown SigHash Type { value } ") ;
66+ sighash_type = value ;
67+ }
68+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_REDEEMSCRIPT , out b ) )
69+ redeem_script = Script . FromBytesUnsafe ( b ) ;
70+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_WITNESSSCRIPT , out b ) )
71+ witness_script = Script . FromBytesUnsafe ( b ) ;
72+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_TAP_KEY_SIG , out b ) )
73+ {
74+ if ( ! TaprootSignature . TryParse ( b , out var sig ) )
75+ throw new FormatException ( "Invalid PSBTInput. Contains invalid TaprootSignature" ) ;
76+ TaprootKeySignature = sig ;
77+ }
78+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_TAP_INTERNAL_KEY , out b ) )
79+ {
80+ if ( ! TaprootInternalPubKey . TryCreate ( b , out var tpk ) )
81+ throw new FormatException ( "Invalid PSBTInput. Contains invalid internal taproot pubkey" ) ;
82+ TaprootInternalKey = tpk ;
83+ }
84+ foreach ( var kv in map . RemoveAll < byte [ ] > ( PSBTConstants . PSBT_IN_BIP32_DERIVATION ) )
85+ {
86+ var pubkey2 = new PubKey ( kv . Key . Skip ( 1 ) . ToArray ( ) ) ;
87+ if ( hd_keypaths . ContainsKey ( pubkey2 ) )
88+ throw new FormatException ( "Invalid PSBTInput. Duplicate key for hd_keypaths" ) ;
89+ var masterFingerPrint = new HDFingerprint ( kv . Value . Take ( 4 ) . ToArray ( ) ) ;
90+ KeyPath path = KeyPath . FromBytes ( kv . Value . Skip ( 4 ) . ToArray ( ) ) ;
91+ hd_keypaths . Add ( pubkey2 , new RootedKeyPath ( masterFingerPrint , path ) ) ;
92+ }
93+ foreach ( var kv in map . RemoveAll < byte [ ] > ( PSBTConstants . PSBT_IN_TAP_BIP32_DERIVATION ) )
94+ {
95+ var pubkey3 = new TaprootPubKey ( kv . Key . Skip ( 1 ) . ToArray ( ) ) ;
96+ if ( hd_taprootkeypaths . ContainsKey ( pubkey3 ) )
97+ throw new FormatException (
98+ "Invalid PSBTOutput, duplicate key for PSBT_IN_TAP_BIP32_DERIVATION" ) ;
99+ var bs = new BitcoinStream ( kv . Value ) ;
100+ List < uint256 > hashes = null ! ;
101+ bs . ReadWrite ( ref hashes ) ;
102+ var pos = ( int ) bs . Inner . Position ;
103+ KeyPath path2 = KeyPath . FromBytes ( kv . Value . Skip ( pos + 4 ) . ToArray ( ) ) ;
104+ hd_taprootkeypaths . Add ( pubkey3 ,
105+ new TaprootKeyPath (
106+ new RootedKeyPath ( new HDFingerprint ( kv . Value . Skip ( pos ) . Take ( 4 ) . ToArray ( ) ) , path2 ) ,
107+ hashes . ToArray ( ) ) ) ;
108+ }
109+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_TAP_MERKLE_ROOT , out b ) )
110+ {
111+ if ( b . Length != 32 )
112+ throw new FormatException (
113+ "Invalid PSBTInput. Unexpected value length for PSBT_IN_TAP_MERKLE_ROOT" ) ;
114+ TaprootMerkleRoot = new uint256 ( b ) ;
175115 }
116+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_SCRIPTSIG , out b ) )
117+ FinalScriptSig = Script . FromBytesUnsafe ( b ) ;
118+ if ( map . TryRemove < byte [ ] > ( PSBTConstants . PSBT_IN_SCRIPTWITNESS , out b ) )
119+ FinalScriptWitness = new WitScript ( b ) ;
120+ unknown = map ;
176121 }
177122
178123 public abstract Sequence Sequence { get ; set ; }
@@ -575,7 +520,7 @@ public IList<PSBTError> CheckSanity()
575520
576521 public bool ? IsNonWitnessUTXOMissing ( )
577522 {
578- if ( ! Parent . Network . Consensus . NeverNeedPreviousTxForSigning || non_witness_utxo is not null )
523+ if ( Parent . Network . Consensus . NeverNeedPreviousTxForSigning || non_witness_utxo is not null )
579524 return false ;
580525 if ( witness_utxo ? . ScriptPubKey is not Script s )
581526 return null ;
0 commit comments