5
5
import org .assertj .core .api .Assertions ;
6
6
import org .junit .Test ;
7
7
import org .twostack .bitcoin4j .Address ;
8
+ import org .twostack .bitcoin4j .Coin ;
8
9
import org .twostack .bitcoin4j .PrivateKey ;
9
10
import org .twostack .bitcoin4j .Utils ;
10
11
import org .twostack .bitcoin4j .exception .InvalidKeyException ;
11
12
import org .twostack .bitcoin4j .exception .SigHashException ;
12
13
import org .twostack .bitcoin4j .exception .SignatureDecodeException ;
13
14
import org .twostack .bitcoin4j .exception .TransactionException ;
14
15
import org .twostack .bitcoin4j .params .NetworkAddressType ;
16
+ import org .twostack .bitcoin4j .script .Interpreter ;
17
+ import org .twostack .bitcoin4j .script .Script ;
15
18
16
19
import java .io .IOException ;
17
20
import java .io .InputStreamReader ;
18
21
import java .math .BigInteger ;
19
22
import java .nio .charset .StandardCharsets ;
23
+ import java .util .Arrays ;
20
24
import java .util .HashMap ;
25
+ import java .util .HashSet ;
26
+ import java .util .Set ;
21
27
22
28
public class TransactionBuilderTest {
23
29
@@ -55,10 +61,35 @@ public void processAndSignMultiInput() throws IOException, InvalidKeyException,
55
61
56
62
57
63
Assertions .assertThatCode (() -> {
58
- Transaction broadcastTx = builder .withFeePerKb (512 )
64
+ Transaction broadcastTx = builder .withFeePerKb (1024 )
59
65
.spendTo (new P2PKHLockBuilder (recipientAddress ), BigInteger .valueOf (100000 ))
60
66
.sendChangeTo (recipientAddress )
61
67
.build (true );
68
+
69
+ //new Script Interpreter to help us verify our spending conditions
70
+ Interpreter interp = new Interpreter ();
71
+
72
+ //loop over every one of our spending inputs and verify we are
73
+ //correctly spending those outputs
74
+ for (int scriptSigIndex = 0 ; scriptSigIndex < 0 ; scriptSigIndex ++) {
75
+ TransactionInput spendingInputOne = TransactionInput .fromByteArray (broadcastTx .getInputs ().get (0 ).serialize ());
76
+ String fundingTxId = Utils .HEX .encode (spendingInputOne .getPrevTxnId ());
77
+ Integer fundingOutputIndex = json .get (scriptSigIndex ).get ("tx_pos" ).asInt ();
78
+ Long fundingValue = json .get (scriptSigIndex ).get ("value" ).asLong ();
79
+
80
+ //lookup funding transaction corresponding to first output
81
+ String rawFundingTx = json .get (scriptSigIndex ).get ("raw_tx" ).asText ();
82
+ Transaction fundingTxOne = Transaction .fromHex (rawFundingTx );
83
+ TransactionOutput fundingOutput = fundingTxOne .getOutputs ().get (fundingOutputIndex );
84
+
85
+ TransactionSigner signer = new TransactionSigner (SigHashType .FORKID .value | SigHashType .ALL .value , privateKey );
86
+ Transaction signedTx = signer .sign (broadcastTx , fundingOutput , scriptSigIndex );
87
+
88
+ //assert that funding transaction is spending correctly
89
+ Set <Script .VerifyFlag > verifyFlags = new HashSet <Script .VerifyFlag >(Arrays .asList (Script .VerifyFlag .SIGHASH_FORKID ));
90
+ interp .correctlySpends (signedTx .getInputs ().get (scriptSigIndex ).getScriptSig (), fundingOutput .getScript (), broadcastTx , scriptSigIndex , verifyFlags , Coin .valueOf (fundingValue ));
91
+ }
92
+
62
93
}).doesNotThrowAnyException ();
63
94
64
95
}
@@ -101,6 +132,30 @@ public void builderCanSpendFromOutput() throws InvalidKeyException, IOException
101
132
.spendTo (new P2PKHLockBuilder (recipientAddress ), BigInteger .valueOf (100000 ))
102
133
.sendChangeTo (recipientAddress )
103
134
.build (true );
135
+
136
+ //new Script Interpreter to help us verify our spending conditions
137
+ Interpreter interp = new Interpreter ();
138
+
139
+ //loop over every one of our spending inputs and verify we are
140
+ //correctly spending those outputs
141
+ for (int scriptSigIndex = 0 ; scriptSigIndex < 0 ; scriptSigIndex ++) {
142
+ TransactionInput spendingInputOne = TransactionInput .fromByteArray (broadcastTx .getInputs ().get (0 ).serialize ());
143
+ String fundingTxId = Utils .HEX .encode (spendingInputOne .getPrevTxnId ());
144
+ Integer fundingOutputIndex = json .get (scriptSigIndex ).get ("tx_pos" ).asInt ();
145
+ Long fundingValue = json .get (scriptSigIndex ).get ("value" ).asLong ();
146
+
147
+ //lookup funding transaction corresponding to first output
148
+ String rawFundingTx = json .get (scriptSigIndex ).get ("raw_tx" ).asText ();
149
+ Transaction fundingTxOne = Transaction .fromHex (rawFundingTx );
150
+ TransactionOutput fundingOutput = fundingTxOne .getOutputs ().get (fundingOutputIndex );
151
+
152
+ TransactionSigner signer = new TransactionSigner (SigHashType .FORKID .value | SigHashType .ALL .value , privateKey );
153
+ Transaction signedTx = signer .sign (broadcastTx , fundingOutput , scriptSigIndex );
154
+
155
+ //assert that funding transaction is spending correctly
156
+ Set <Script .VerifyFlag > verifyFlags = new HashSet <Script .VerifyFlag >(Arrays .asList (Script .VerifyFlag .SIGHASH_FORKID ));
157
+ interp .correctlySpends (signedTx .getInputs ().get (scriptSigIndex ).getScriptSig (), fundingOutput .getScript (), broadcastTx , scriptSigIndex , verifyFlags , Coin .valueOf (fundingValue ));
158
+ }
104
159
}).doesNotThrowAnyException ();
105
160
106
161
}
@@ -152,6 +207,30 @@ public void builderCanSpendFromOutpoint() throws InvalidKeyException, IOExceptio
152
207
.spendTo (new P2PKHLockBuilder (recipientAddress ), BigInteger .valueOf (100000 ))
153
208
.sendChangeTo (recipientAddress )
154
209
.build (true );
210
+
211
+ //new Script Interpreter to help us verify our spending conditions
212
+ Interpreter interp = new Interpreter ();
213
+
214
+ //loop over every one of our spending inputs and verify we are
215
+ //correctly spending those outputs
216
+ for (int scriptSigIndex = 0 ; scriptSigIndex < 0 ; scriptSigIndex ++) {
217
+ TransactionInput spendingInputOne = TransactionInput .fromByteArray (broadcastTx .getInputs ().get (0 ).serialize ());
218
+ String fundingTxId = Utils .HEX .encode (spendingInputOne .getPrevTxnId ());
219
+ Integer fundingOutputIndex = json .get (scriptSigIndex ).get ("tx_pos" ).asInt ();
220
+ Long fundingValue = json .get (scriptSigIndex ).get ("value" ).asLong ();
221
+
222
+ //lookup funding transaction corresponding to first output
223
+ String rawFundingTx = json .get (scriptSigIndex ).get ("raw_tx" ).asText ();
224
+ Transaction fundingTxOne = Transaction .fromHex (rawFundingTx );
225
+ TransactionOutput fundingOutput = fundingTxOne .getOutputs ().get (fundingOutputIndex );
226
+
227
+ TransactionSigner signer = new TransactionSigner (SigHashType .FORKID .value | SigHashType .ALL .value , privateKey );
228
+ Transaction signedTx = signer .sign (broadcastTx , fundingOutput , scriptSigIndex );
229
+
230
+ //assert that funding transaction is spending correctly
231
+ Set <Script .VerifyFlag > verifyFlags = new HashSet <Script .VerifyFlag >(Arrays .asList (Script .VerifyFlag .SIGHASH_FORKID ));
232
+ interp .correctlySpends (signedTx .getInputs ().get (scriptSigIndex ).getScriptSig (), fundingOutput .getScript (), broadcastTx , scriptSigIndex , verifyFlags , Coin .valueOf (fundingValue ));
233
+ }
155
234
}).doesNotThrowAnyException ();
156
235
}
157
236
@@ -165,6 +244,7 @@ public void builderCanSpendFromUtxoMap() throws InvalidKeyException, IOException
165
244
String wif = "cRTUuWgPdp7tJPrn1Xeq196eZa4ZCpg8n3cgDJsJmgDHBZ8x9fpv" ;
166
245
PrivateKey privateKey = PrivateKey .fromWIF (wif );
167
246
247
+ System .out .println (Address .fromKey (NetworkAddressType .TEST_PKH , privateKey .getPublicKey ()).toString ());
168
248
JsonNode json = new ObjectMapper ().readTree (
169
249
new InputStreamReader (getClass ().getResourceAsStream ("multi_input.json" ),
170
250
StandardCharsets .UTF_8 )
@@ -202,6 +282,30 @@ public void builderCanSpendFromUtxoMap() throws InvalidKeyException, IOException
202
282
.spendTo (new P2PKHLockBuilder (recipientAddress ), BigInteger .valueOf (100000 ))
203
283
.sendChangeTo (recipientAddress )
204
284
.build (true );
285
+
286
+ //new Script Interpreter to help us verify our spending conditions
287
+ Interpreter interp = new Interpreter ();
288
+
289
+ //loop over every one of our spending inputs and verify we are
290
+ //correctly spending those outputs
291
+ for (int scriptSigIndex = 0 ; scriptSigIndex < 0 ; scriptSigIndex ++) {
292
+ TransactionInput spendingInputOne = TransactionInput .fromByteArray (broadcastTx .getInputs ().get (0 ).serialize ());
293
+ String fundingTxId = Utils .HEX .encode (spendingInputOne .getPrevTxnId ());
294
+ Integer fundingOutputIndex = json .get (scriptSigIndex ).get ("tx_pos" ).asInt ();
295
+ Long fundingValue = json .get (scriptSigIndex ).get ("value" ).asLong ();
296
+
297
+ //lookup funding transaction corresponding to first output
298
+ String rawFundingTx = json .get (scriptSigIndex ).get ("raw_tx" ).asText ();
299
+ Transaction fundingTxOne = Transaction .fromHex (rawFundingTx );
300
+ TransactionOutput fundingOutput = fundingTxOne .getOutputs ().get (fundingOutputIndex );
301
+
302
+ TransactionSigner signer = new TransactionSigner (SigHashType .FORKID .value | SigHashType .ALL .value , privateKey );
303
+ Transaction signedTx = signer .sign (broadcastTx , fundingOutput , scriptSigIndex );
304
+
305
+ //assert that funding transaction is spending correctly
306
+ Set <Script .VerifyFlag > verifyFlags = new HashSet <Script .VerifyFlag >(Arrays .asList (Script .VerifyFlag .SIGHASH_FORKID ));
307
+ interp .correctlySpends (signedTx .getInputs ().get (scriptSigIndex ).getScriptSig (), fundingOutput .getScript (), broadcastTx , scriptSigIndex , verifyFlags , Coin .valueOf (fundingValue ));
308
+ }
205
309
}).doesNotThrowAnyException ();
206
310
}
207
311
}
0 commit comments