Script: make field chunks immutable

Also rename the accessor to `chunks()`.
This commit is contained in:
Andreas Schildbach 2023-04-05 17:05:30 +02:00
parent 2444fad85b
commit 131b37f5d2
15 changed files with 85 additions and 75 deletions

View File

@ -346,7 +346,7 @@ public class BloomFilter extends Message {
BloomUpdate flag = getUpdateFlag();
for (TransactionOutput output : tx.getOutputs()) {
Script script = output.getScriptPubKey();
for (ScriptChunk chunk : script.getChunks()) {
for (ScriptChunk chunk : script.chunks()) {
if (!chunk.isPushData())
continue;
if (contains(chunk.data)) {
@ -362,7 +362,7 @@ public class BloomFilter extends Message {
if (contains(input.getOutpoint().serialize())) {
return true;
}
for (ScriptChunk chunk : input.getScriptSig().getChunks()) {
for (ScriptChunk chunk : input.getScriptSig().chunks()) {
if (chunk.isPushData() && contains(chunk.data))
return true;
}

View File

@ -866,7 +866,7 @@ public class Transaction extends Message {
s.append("out ");
try {
Script scriptPubKey = out.getScriptPubKey();
s.append(scriptPubKey.getChunks().size() > 0 ? scriptPubKey.toString() : "<no scriptPubKey>");
s.append(scriptPubKey.chunks().size() > 0 ? scriptPubKey.toString() : "<no scriptPubKey>");
s.append(" ");
s.append(out.getValue().toFriendlyString());
s.append('\n');

View File

@ -221,7 +221,7 @@ public class Script {
public static final int MAX_P2SH_SIGOPS = 15;
// The program is a set of chunks where each element is either [opcode] or [data, data, data ...]
protected List<ScriptChunk> chunks;
private final List<ScriptChunk> chunks;
// Unfortunately, scripts are not ever re-serialized or canonicalized when used in signature hashing. Thus we
// must preserve the exact bytes that we read off the wire, along with the parsed form.
protected byte[] program;
@ -333,6 +333,21 @@ public class Script {
this.creationTime = creationTime;
}
/**
* Gets an immutable list of the scripts parsed form. Each chunk is either an opcode or data element.
*
* @return script chunks
*/
public List<ScriptChunk> chunks() {
return Collections.unmodifiableList(chunks);
}
/** @deprecated use {@link #chunks()} */
@Deprecated
public List<ScriptChunk> getChunks() {
return chunks();
}
/**
* Gets the creation time of this script, or empty if unknown.
* @return creation time of this script, or empty if unknown
@ -402,11 +417,6 @@ public class Script {
}
}
/** Returns an immutable list of the scripts parsed form. Each chunk is either an opcode or data element. */
public List<ScriptChunk> getChunks() {
return Collections.unmodifiableList(chunks);
}
private static final ScriptChunk[] STANDARD_TRANSACTION_SCRIPT_CHUNKS = {
new ScriptChunk(ScriptOpCodes.OP_DUP, null),
new ScriptChunk(ScriptOpCodes.OP_HASH160, null),

View File

@ -70,7 +70,7 @@ public class ScriptBuilder {
/** Creates a fresh ScriptBuilder with the given program as the starting point. */
public ScriptBuilder(Script template) {
chunks = new ArrayList<>(template.getChunks());
chunks = new ArrayList<>(template.chunks());
}
/**
@ -433,7 +433,7 @@ public class ScriptBuilder {
public static Script updateScriptWithSignature(Script scriptSig, byte[] signature, int targetIndex,
int sigsPrefixCount, int sigsSuffixCount) {
ScriptBuilder builder = new ScriptBuilder();
List<ScriptChunk> inputChunks = scriptSig.getChunks();
List<ScriptChunk> inputChunks = scriptSig.chunks();
int totalChunks = inputChunks.size();
// Check if we have a place to insert, otherwise just return given scriptSig unchanged.

View File

@ -48,7 +48,7 @@ public class ScriptPattern {
* way to make payments due to the short and recognizable base58 form addresses come in.
*/
public static boolean isP2PKH(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (chunks.size() != 5)
return false;
if (!chunks.get(0).equalsOpCode(OP_DUP))
@ -72,7 +72,7 @@ public class ScriptPattern {
* will want to guard calls to this method with {@link #isP2PKH(Script)}.
*/
public static byte[] extractHashFromP2PKH(Script script) {
return script.chunks.get(2).data;
return script.chunks().get(2).data;
}
/**
@ -86,7 +86,7 @@ public class ScriptPattern {
* </p>
*/
public static boolean isP2SH(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
// We check for the effective serialized form because BIP16 defines a P2SH output using an exact byte
// template, not the logical program structure. Thus you can have two programs that look identical when
// printed out but one is a P2SH script and the other isn't! :(
@ -114,7 +114,7 @@ public class ScriptPattern {
* will want to guard calls to this method with {@link #isP2SH(Script)}.
*/
public static byte[] extractHashFromP2SH(Script script) {
return script.chunks.get(1).data;
return script.chunks().get(1).data;
}
/**
@ -124,7 +124,7 @@ public class ScriptPattern {
* useful more exotic types of transaction, but today most payments are to addresses.
*/
public static boolean isP2PK(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (chunks.size() != 2)
return false;
ScriptChunk chunk0 = chunks.get(0);
@ -145,7 +145,7 @@ public class ScriptPattern {
* want to guard calls to this method with {@link #isP2PK(Script)}.
*/
public static byte[] extractKeyFromP2PK(Script script) {
return script.chunks.get(0).data;
return script.chunks().get(0).data;
}
/**
@ -153,7 +153,7 @@ public class ScriptPattern {
* two script types were introduced with segwit.
*/
public static boolean isP2WH(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (chunks.size() != 2)
return false;
if (!chunks.get(0).equalsOpCode(OP_0))
@ -174,7 +174,7 @@ public class ScriptPattern {
public static boolean isP2WPKH(Script script) {
if (!isP2WH(script))
return false;
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (!chunks.get(0).equalsOpCode(OP_0))
return false;
byte[] chunk1data = chunks.get(1).data;
@ -188,7 +188,7 @@ public class ScriptPattern {
public static boolean isP2WSH(Script script) {
if (!isP2WH(script))
return false;
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (!chunks.get(0).equalsOpCode(OP_0))
return false;
byte[] chunk1data = chunks.get(1).data;
@ -201,7 +201,7 @@ public class ScriptPattern {
* {@link #isP2WH(Script)}.
*/
public static byte[] extractHashFromP2WH(Script script) {
return script.chunks.get(1).data;
return script.chunks().get(1).data;
}
/**
@ -209,7 +209,7 @@ public class ScriptPattern {
* script type was introduced with taproot.
*/
public static boolean isP2TR(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (chunks.size() != 2)
return false;
if (!chunks.get(0).equalsOpCode(OP_1))
@ -227,7 +227,7 @@ public class ScriptPattern {
* form, so you will want to guard calls to this method with {@link #isP2TR(Script)}.
*/
public static byte[] extractOutputKeyFromP2TR(Script script) {
return script.chunks.get(1).data;
return script.chunks().get(1).data;
}
/**
@ -235,7 +235,7 @@ public class ScriptPattern {
* {@code [m] [keys...] [n] CHECKMULTISIG}
*/
public static boolean isSentToMultisig(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (chunks.size() < 4) return false;
ScriptChunk chunk = chunks.get(chunks.size() - 1);
// Must end in OP_CHECKMULTISIG[VERIFY].
@ -257,7 +257,7 @@ public class ScriptPattern {
* Returns whether this script is using OP_RETURN to store arbitrary data.
*/
public static boolean isOpReturn(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
return chunks.size() > 0 && chunks.get(0).equalsOpCode(ScriptOpCodes.OP_RETURN);
}
@ -268,7 +268,7 @@ public class ScriptPattern {
* transaction).
*/
public static boolean isWitnessCommitment(Script script) {
List<ScriptChunk> chunks = script.chunks;
List<ScriptChunk> chunks = script.chunks();
if (chunks.size() < 2)
return false;
if (!chunks.get(0).equalsOpCode(ScriptOpCodes.OP_RETURN))
@ -285,6 +285,6 @@ public class ScriptPattern {
* Retrieves the hash from a segwit commitment (in an output of the coinbase transaction).
*/
public static Sha256Hash extractWitnessCommitmentHash(Script script) {
return Sha256Hash.wrap(Arrays.copyOfRange(script.chunks.get(1).data, 4, 36));
return Sha256Hash.wrap(Arrays.copyOfRange(script.chunks().get(1).data, 4, 36));
}
}

View File

@ -74,8 +74,8 @@ public class MissingSigResolutionSigner implements TransactionSigner {
if (ScriptPattern.isP2SH(scriptPubKey) || ScriptPattern.isSentToMultisig(scriptPubKey)) {
int sigSuffixCount = ScriptPattern.isP2SH(scriptPubKey) ? 1 : 0;
// all chunks except the first one (OP_0) and the last (redeem script) are signatures
for (int j = 1; j < inputScript.getChunks().size() - sigSuffixCount; j++) {
ScriptChunk scriptChunk = inputScript.getChunks().get(j);
for (int j = 1; j < inputScript.chunks().size() - sigSuffixCount; j++) {
ScriptChunk scriptChunk = inputScript.chunks().get(j);
if (scriptChunk.equalsOpCode(0)) {
if (missingSigsMode == Wallet.MissingSigsMode.THROW) {
throw new MissingSignatureException();
@ -85,7 +85,7 @@ public class MissingSigResolutionSigner implements TransactionSigner {
}
}
} else if (ScriptPattern.isP2PK(scriptPubKey) || ScriptPattern.isP2PKH(scriptPubKey)) {
if (inputScript.getChunks().get(0).equalsOpCode(0)) {
if (inputScript.chunks().get(0).equalsOpCode(0)) {
if (missingSigsMode == Wallet.MissingSigsMode.THROW) {
throw new ECKey.MissingPrivateKeyException();
} else if (missingSigsMode == Wallet.MissingSigsMode.USE_DUMMY_SIG) {

View File

@ -173,7 +173,7 @@ public class DefaultRiskAnalysis implements RiskAnalysis {
public static RuleViolation isOutputStandard(TransactionOutput output) {
if (output.isDust())
return RuleViolation.DUST;
for (ScriptChunk chunk : output.getScriptPubKey().getChunks()) {
for (ScriptChunk chunk : output.getScriptPubKey().chunks()) {
if (chunk.isPushData() && !chunk.isShortestPossiblePushData())
return RuleViolation.SHORTEST_POSSIBLE_PUSHDATA;
}
@ -182,7 +182,7 @@ public class DefaultRiskAnalysis implements RiskAnalysis {
/** Checks if the given input passes some of the AreInputsStandard checks. Not complete. */
public static RuleViolation isInputStandard(TransactionInput input) {
for (ScriptChunk chunk : input.getScriptSig().getChunks()) {
for (ScriptChunk chunk : input.getScriptSig().chunks()) {
if (chunk.data != null && !chunk.isShortestPossiblePushData())
return RuleViolation.SHORTEST_POSSIBLE_PUSHDATA;
if (chunk.isPushData()) {

View File

@ -5099,7 +5099,7 @@ public class Wallet extends BaseTaggableObject
try {
BloomFilter filter = keyChainGroup.getBloomFilter(size, falsePositiveRate, nTweak);
for (Script script : watchedScripts) {
for (ScriptChunk chunk : script.getChunks()) {
for (ScriptChunk chunk : script.chunks()) {
// Only add long (at least 64 bit) data to the bloom filter.
// If any long constants become popular in scripts, we will need logic
// here to exclude them.

View File

@ -1800,7 +1800,7 @@ public class FullBlockTestGenerator {
input.setSequenceNumber(sequence);
t.addInput(input);
if (prevOut.scriptPubKey.getChunks().get(0).equalsOpCode(OP_TRUE)) {
if (prevOut.scriptPubKey.chunks().get(0).equalsOpCode(OP_TRUE)) {
input.setScriptSig(new ScriptBuilder().op(OP_1).build());
} else {
// Sign input

View File

@ -30,7 +30,7 @@ public class ScriptBuilderTest {
public void testNumber() {
for (int i = -100; i <= 100; i++) {
Script s = new ScriptBuilder().number(i).build();
for (ScriptChunk ch : s.chunks) {
for (ScriptChunk ch : s.chunks()) {
assertTrue(Integer.toString(i), ch.isShortestPossiblePushData());
}
}

View File

@ -57,15 +57,15 @@ public class ScriptChunkTest {
@Test
public void testShortestPossibleDataPush() {
assertTrue("empty push", new ScriptBuilder().data(new byte[0]).build().getChunks().get(0)
assertTrue("empty push", new ScriptBuilder().data(new byte[0]).build().chunks().get(0)
.isShortestPossiblePushData());
for (byte i = -1; i < 127; i++)
assertTrue("push of single byte " + i, new ScriptBuilder().data(new byte[] { i }).build().getChunks()
assertTrue("push of single byte " + i, new ScriptBuilder().data(new byte[] { i }).build().chunks()
.get(0).isShortestPossiblePushData());
for (int len = 2; len < Script.MAX_SCRIPT_ELEMENT_SIZE; len++)
assertTrue("push of " + len + " bytes", new ScriptBuilder().data(new byte[len]).build().getChunks().get(0)
assertTrue("push of " + len + " bytes", new ScriptBuilder().data(new byte[len]).build().chunks().get(0)
.isShortestPossiblePushData());
// non-standard chunks

View File

@ -171,22 +171,22 @@ public class ScriptTest {
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(Arrays.asList(party1TransactionSignature, party2TransactionSignature), multisigScript);
// Assert that the input script contains 4 chunks
assertTrue(inputScript.getChunks().size() == 4);
assertTrue(inputScript.chunks().size() == 4);
// Assert that the input script created contains the original multisig
// script as the last chunk
ScriptChunk scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
ScriptChunk scriptChunk = inputScript.chunks().get(inputScript.chunks().size() - 1);
assertArrayEquals(scriptChunk.data, multisigScript.getProgram());
// Create regular multisig input script
inputScript = ScriptBuilder.createMultiSigInputScript(Arrays.asList(party1TransactionSignature, party2TransactionSignature));
// Assert that the input script only contains 3 chunks
assertTrue(inputScript.getChunks().size() == 3);
assertTrue(inputScript.chunks().size() == 3);
// Assert that the input script created does not end with the original
// multisig script
scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
scriptChunk = inputScript.chunks().get(inputScript.chunks().size() - 1);
assertThat(scriptChunk.data, IsNot.not(equalTo(multisigScript.getProgram())));
}
@ -197,43 +197,43 @@ public class ScriptTest {
// P2PK
Script inputScript = ScriptBuilder.createInputScript(dummySig);
assertThat(inputScript.getChunks().get(0).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.chunks().get(0).data, equalTo(dummySig.encodeToBitcoin()));
inputScript = ScriptBuilder.createInputScript(null);
assertThat(inputScript.getChunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(0).opcode, equalTo(OP_0));
// P2PKH
inputScript = ScriptBuilder.createInputScript(dummySig, key);
assertThat(inputScript.getChunks().get(0).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.chunks().get(0).data, equalTo(dummySig.encodeToBitcoin()));
inputScript = ScriptBuilder.createInputScript(null, key);
assertThat(inputScript.getChunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(1).data, equalTo(key.getPubKey()));
assertThat(inputScript.chunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(1).data, equalTo(key.getPubKey()));
// P2SH
ECKey key2 = new ECKey();
Script multisigScript = ScriptBuilder.createMultiSigOutputScript(2, Arrays.asList(key, key2));
inputScript = ScriptBuilder.createP2SHMultiSigInputScript(Arrays.asList(dummySig, dummySig), multisigScript);
assertThat(inputScript.getChunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(1).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.getChunks().get(2).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.getChunks().get(3).data, equalTo(multisigScript.getProgram()));
assertThat(inputScript.chunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(1).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.chunks().get(2).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.chunks().get(3).data, equalTo(multisigScript.getProgram()));
inputScript = ScriptBuilder.createP2SHMultiSigInputScript(null, multisigScript);
assertThat(inputScript.getChunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(1).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(2).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(3).data, equalTo(multisigScript.getProgram()));
assertThat(inputScript.chunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(1).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(2).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(3).data, equalTo(multisigScript.getProgram()));
inputScript = ScriptBuilder.updateScriptWithSignature(inputScript, dummySig.encodeToBitcoin(), 0, 1, 1);
assertThat(inputScript.getChunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(1).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.getChunks().get(2).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(3).data, equalTo(multisigScript.getProgram()));
assertThat(inputScript.chunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(1).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.chunks().get(2).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(3).data, equalTo(multisigScript.getProgram()));
inputScript = ScriptBuilder.updateScriptWithSignature(inputScript, dummySig.encodeToBitcoin(), 1, 1, 1);
assertThat(inputScript.getChunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.getChunks().get(1).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.getChunks().get(2).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.getChunks().get(3).data, equalTo(multisigScript.getProgram()));
assertThat(inputScript.chunks().get(0).opcode, equalTo(OP_0));
assertThat(inputScript.chunks().get(1).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.chunks().get(2).data, equalTo(dummySig.encodeToBitcoin()));
assertThat(inputScript.chunks().get(3).data, equalTo(multisigScript.getProgram()));
// updating scriptSig with no missing signatures
try {

View File

@ -208,7 +208,7 @@ public class DefaultRiskAnalysisTest {
"010000000200a2be4376b7f47250ad9ad3a83b6aa5eb6a6d139a1f50771704d77aeb8ce76c010000006a4730440220055723d363cd2d4fe4e887270ebdf5c4b99eaf233a5c09f9404f888ec8b839350220763c3794d310b384ce86decfb05787e5bfa5d31983db612a2dde5ffec7f396ae012102ef47e27e0c4bdd6dc83915f185d972d5eb8515c34d17bad584a9312e59f4e0bcffffffff52239451d37757eeacb86d32864ec1ee6b6e131d1e3fee6f1cff512703b71014030000006c493046022100ea266ac4f893d98a623a6fc0e6a961cd5a3f32696721e87e7570a68851917e75022100a928a3c4898be60909347e765f52872a613d8aada66c57a8c8791316d2f298710121038bb455ca101ebbb0ecf7f5c01fa1dcb7d14fbf6b7d7ea52ee56f0148e72a736cffffffff0630b15a00000000001976a9146ae477b690cf85f21c2c01e2c8639a5c18dc884e88ac4f260d00000000001976a91498d08c02ab92a671590adb726dddb719695ee12e88ac65753b00000000001976a9140b2eb4ba6d364c82092f25775f56bc10cd92c8f188ac65753b00000000001976a914d1cb414e22081c6ba3a935635c0f1d837d3c5d9188ac65753b00000000001976a914df9d137a0d279471a2796291874c29759071340b88ac3d753b00000000001976a91459f5aa4815e3aa8e1720e8b82f4ac8e6e904e47d88ac00000000")));
assertEquals("dbe4147cf89b89fd9fa6c8ce6a3e2adecb234db094ec88301ae09073ca17d61d", tx2.getTxId().toString());
assertFalse(ECKey.ECDSASignature
.decodeFromDER(Script.parse(tx2.getInput(1).getScriptBytes()).getChunks().get(0).data)
.decodeFromDER(Script.parse(tx2.getInput(1).getScriptBytes()).chunks().get(0).data)
.isCanonical());
assertEquals(RuleViolation.SIGNATURE_CANONICAL_ENCODING, DefaultRiskAnalysis.isStandard(tx2));

View File

@ -546,7 +546,7 @@ public class WalletTest extends TestWithWallet {
// Do some basic sanity checks.
assertEquals(1, t2.getInputs().size());
List<ScriptChunk> scriptSigChunks = t2.getInput(0).getScriptSig().getChunks();
List<ScriptChunk> scriptSigChunks = t2.getInput(0).getScriptSig().chunks();
// check 'from address' -- in a unit test this is fine
assertEquals(2, scriptSigChunks.size());
assertEquals(myAddress, LegacyAddress.fromPubKeyHash(BitcoinNetwork.TESTNET, CryptoUtils.sha256hash160(scriptSigChunks.get(1).data)));
@ -1571,8 +1571,8 @@ public class WalletTest extends TestWithWallet {
Transaction t2 = wallet.createSend(OTHER_ADDRESS, value);
assertNotNull(t2);
// TODO: This code is messy, improve the Script class and fixinate!
assertEquals(t2.toString(), 1, t2.getInput(0).getScriptSig().getChunks().size());
assertTrue(t2.getInput(0).getScriptSig().getChunks().get(0).data.length > 50);
assertEquals(t2.toString(), 1, t2.getInput(0).getScriptSig().chunks().size());
assertTrue(t2.getInput(0).getScriptSig().chunks().get(0).data.length > 50);
}
@Test
@ -3123,12 +3123,12 @@ public class WalletTest extends TestWithWallet {
wallet.completeTx(req);
TransactionInput input = req.tx.getInput(0);
boolean firstSigIsMissing = Arrays.equals(expectedSig, input.getScriptSig().getChunks().get(1).data);
boolean secondSigIsMissing = Arrays.equals(expectedSig, input.getScriptSig().getChunks().get(2).data);
boolean firstSigIsMissing = Arrays.equals(expectedSig, input.getScriptSig().chunks().get(1).data);
boolean secondSigIsMissing = Arrays.equals(expectedSig, input.getScriptSig().chunks().get(2).data);
assertTrue("Only one of the signatures should be missing/dummy", firstSigIsMissing ^ secondSigIsMissing);
int localSigIndex = firstSigIsMissing ? 2 : 1;
int length = input.getScriptSig().getChunks().get(localSigIndex).data.length;
int length = input.getScriptSig().chunks().get(localSigIndex).data.length;
assertTrue("Local sig should be present: " + length, length >= 70);
}
@ -3155,9 +3155,9 @@ public class WalletTest extends TestWithWallet {
for (int i = 0; i < req.tx.getInputs().size(); i++) {
TransactionInput input = req.tx.getInput(i);
if (input.getConnectedOutput().getParentTransaction().equals(t1)) {
assertArrayEquals(expectedSig, input.getScriptSig().getChunks().get(0).data);
assertArrayEquals(expectedSig, input.getScriptSig().chunks().get(0).data);
} else if (input.getConnectedOutput().getParentTransaction().equals(t2)) {
assertArrayEquals(expectedSig, input.getScriptSig().getChunks().get(0).data);
assertArrayEquals(expectedSig, input.getScriptSig().chunks().get(0).data);
} else if (input.getConnectedOutput().getParentTransaction().equals(t3)) {
input.getScriptSig().correctlySpends(
req.tx, i, null, null, t3.getOutput(0).getScriptPubKey(), Script.ALL_VERIFY_FLAGS);

View File

@ -105,7 +105,7 @@ public class GenerateLowSTests {
EnumSet.of(Script.VerifyFlag.DERSIG, Script.VerifyFlag.P2SH));
final Script scriptSig = input.getScriptSig();
final TransactionSignature signature = TransactionSignature.decodeFromBitcoin(scriptSig.getChunks().get(0).data, true, false);
final TransactionSignature signature = TransactionSignature.decodeFromBitcoin(scriptSig.chunks().get(0).data, true, false);
// First output a conventional low-S transaction with the LOW_S flag, for the tx_valid.json set
System.out.println("[\"A transaction with a low-S signature.\"],");
@ -118,7 +118,7 @@ public class GenerateLowSTests {
final BigInteger highS = HIGH_S_DIFFERENCE.subtract(signature.s);
final TransactionSignature highSig = new TransactionSignature(signature.r, highS);
input.setScriptSig(new ScriptBuilder().data(highSig.encodeToBitcoin()).data(scriptSig.getChunks().get(1).data).build());
input.setScriptSig(new ScriptBuilder().data(highSig.encodeToBitcoin()).data(scriptSig.chunks().get(1).data).build());
input.getScriptSig().correctlySpends(outputTransaction, 0, null, null, output.getScriptPubKey(),
EnumSet.of(Script.VerifyFlag.P2SH));
@ -159,7 +159,7 @@ public class GenerateLowSTests {
*/
private static String scriptToString(Script scriptPubKey) {
final StringBuilder buf = new StringBuilder();
for (ScriptChunk chunk: scriptPubKey.getChunks()) {
for (ScriptChunk chunk: scriptPubKey.chunks()) {
if (buf.length() > 0) {
buf.append(" ");
}