From 8e0604a404e10f601935a603a2f99a213fe2c2c8 Mon Sep 17 00:00:00 2001 From: julia-zack Date: Fri, 16 Aug 2024 21:15:20 -0300 Subject: [PATCH 1/6] Create flyover redeem script builder Remove unused import Remove mistaken reason Minor refactor Make flyover rs builder receive a keccak256 hash instead of sha256 one Refactors --- .../bitcoin/FlyoverRedeemScriptBuilder.java | 9 +++ .../FlyoverRedeemScriptBuilderImpl.java | 35 +++++++++ .../FlyoverRedeemScriptCreationException.java | 17 +++++ .../FlyoverRedeemScriptBuilderImplTest.java | 74 +++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java create mode 100644 rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java create mode 100644 rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java create mode 100644 rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java new file mode 100644 index 00000000000..6eb34fab9b9 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java @@ -0,0 +1,9 @@ +package co.rsk.peg.bitcoin; + +import co.rsk.bitcoinj.script.Script; +import co.rsk.crypto.Keccak256; + +public interface FlyoverRedeemScriptBuilder { + Script addFlyoverDerivationHashToRedeemScript(Keccak256 flyoverDerivationHash, Script redeemScript); + +} diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java new file mode 100644 index 00000000000..157e8f44fbf --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java @@ -0,0 +1,35 @@ +package co.rsk.peg.bitcoin; + +import co.rsk.bitcoinj.script.Script; +import co.rsk.bitcoinj.script.ScriptBuilder; +import co.rsk.bitcoinj.script.ScriptOpCodes; +import co.rsk.crypto.Keccak256; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static co.rsk.peg.bitcoin.FlyoverRedeemScriptCreationException.Reason.INVALID_FLYOVER_DERIVATION_HASH; +import static java.util.Objects.isNull; + +public class FlyoverRedeemScriptBuilderImpl implements FlyoverRedeemScriptBuilder { + private static final Logger logger = LoggerFactory.getLogger(FlyoverRedeemScriptBuilderImpl.class); + + public Script addFlyoverDerivationHashToRedeemScript(Keccak256 flyoverDerivationHash, Script redeemScript) { + validateFlyoverDerivationHash(flyoverDerivationHash); + + ScriptBuilder scriptBuilder = new ScriptBuilder(); + byte[] flyoverDerivationHashSerialized = flyoverDerivationHash.getBytes(); + return scriptBuilder + .data(flyoverDerivationHashSerialized) + .op(ScriptOpCodes.OP_DROP) + .addChunks(redeemScript.getChunks()) + .build(); + } + + private void validateFlyoverDerivationHash(Keccak256 flyoverDerivationHash) { + if (isNull(flyoverDerivationHash) || flyoverDerivationHash.equals(Keccak256.ZERO_HASH)) { + String message = String.format("Provided flyover derivation hash %s is invalid.", flyoverDerivationHash); + logger.warn("[validateFlyoverDerivationHash] {}", message); + throw new FlyoverRedeemScriptCreationException(message, INVALID_FLYOVER_DERIVATION_HASH); + } + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java new file mode 100644 index 00000000000..543bab0be7e --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java @@ -0,0 +1,17 @@ +package co.rsk.peg.bitcoin; + +public class FlyoverRedeemScriptCreationException extends RuntimeException { + private final Reason reason; + + public enum Reason { + INVALID_FLYOVER_DERIVATION_HASH + } + + public FlyoverRedeemScriptCreationException(String s, Reason reason) { + super(s); + this.reason = reason; + } + + public Reason getReason() { return reason; } + +} diff --git a/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java b/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java new file mode 100644 index 00000000000..ce41ba00b23 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java @@ -0,0 +1,74 @@ +package co.rsk.peg.bitcoin; + +import co.rsk.bitcoinj.script.Script; +import co.rsk.bitcoinj.script.ScriptChunk; +import co.rsk.bitcoinj.script.ScriptOpCodes; +import co.rsk.crypto.Keccak256; +import co.rsk.peg.federation.Federation; +import co.rsk.peg.federation.P2shErpFederationBuilder; +import org.ethereum.TestUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.List; +import java.util.stream.Stream; + +import static co.rsk.peg.bitcoin.FlyoverRedeemScriptCreationException.Reason.INVALID_FLYOVER_DERIVATION_HASH; +import static org.junit.jupiter.api.Assertions.*; + +class FlyoverRedeemScriptBuilderImplTest { + private Script redeemScript; + private FlyoverRedeemScriptBuilder flyoverRedeemScriptBuilder; + + @BeforeEach + void setUp() { + Federation federation = new P2shErpFederationBuilder().build(); + redeemScript = federation.getRedeemScript(); + flyoverRedeemScriptBuilder = new FlyoverRedeemScriptBuilderImpl(); + } + + @ParameterizedTest + @MethodSource("invalidDerivationHashArgsProvider") + void addFlyoverDerivationHashToRedeemScript_withInvalidPrefix_shouldThrowFlyoverRedeemScriptCreationException(Keccak256 flyoverDerivationHash) { + FlyoverRedeemScriptCreationException exception = assertThrows(FlyoverRedeemScriptCreationException.class, + () -> flyoverRedeemScriptBuilder.addFlyoverDerivationHashToRedeemScript(flyoverDerivationHash, redeemScript)); + + assertEquals(INVALID_FLYOVER_DERIVATION_HASH, exception.getReason()); + + String expectedMessage = String.format("Provided flyover derivation hash %s is invalid.", flyoverDerivationHash); + assertEquals(expectedMessage, exception.getMessage()); + } + + private static Stream invalidDerivationHashArgsProvider() { + return Stream.of(null, Keccak256.ZERO_HASH); + } + + @Test + void addFlyoverDerivationHashToRedeemScript_shouldReturnRedeemScriptWithFlyoverDerivationHash() { + // arrange + Keccak256 flyoverDerivationHash = TestUtils.generateHash("hash"); + + // act + Script redeemScriptWithFlyoverDerivationHash = flyoverRedeemScriptBuilder.addFlyoverDerivationHashToRedeemScript(flyoverDerivationHash, redeemScript); + + // assert + List originalRedeemScriptChunks = getOriginalRedeemScriptChunks(redeemScriptWithFlyoverDerivationHash); + assertEquals(redeemScript.getChunks(), originalRedeemScriptChunks); + + List redeemScriptWithFlyoverDerivationHashChunks = redeemScriptWithFlyoverDerivationHash.getChunks(); + ScriptChunk flyoverDerivationHashChunk = redeemScriptWithFlyoverDerivationHashChunks.get(0); + ScriptChunk opDropChunk = redeemScriptWithFlyoverDerivationHashChunks.get(1); + assertArrayEquals(flyoverDerivationHash.getBytes(), flyoverDerivationHashChunk.data); + assertEquals(ScriptOpCodes.OP_DROP, opDropChunk.opcode); + } + + private List getOriginalRedeemScriptChunks(Script redeemScript) { + List redeemScriptChunks = redeemScript.getChunks(); + int firstOriginalChunkIndex = 2; + int lastOriginalChunkIndex = redeemScriptChunks.size(); + + return redeemScriptChunks.subList(firstOriginalChunkIndex, lastOriginalChunkIndex); + } +} From 0e71532fa75f9ed09579c78b72712cda6e2d9256 Mon Sep 17 00:00:00 2001 From: julia-zack Date: Mon, 19 Aug 2024 13:08:59 -0300 Subject: [PATCH 2/6] Delete FlyoverRedeemScriptCreationException and move flyover reason to RedeemScriptCreationException --- .../bitcoin/FlyoverRedeemScriptBuilderImpl.java | 4 ++-- .../FlyoverRedeemScriptCreationException.java | 17 ----------------- .../bitcoin/RedeemScriptCreationException.java | 3 ++- .../FlyoverRedeemScriptBuilderImplTest.java | 4 ++-- 4 files changed, 6 insertions(+), 22 deletions(-) delete mode 100644 rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java index 157e8f44fbf..abb49055532 100644 --- a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java @@ -7,7 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static co.rsk.peg.bitcoin.FlyoverRedeemScriptCreationException.Reason.INVALID_FLYOVER_DERIVATION_HASH; +import static co.rsk.peg.bitcoin.RedeemScriptCreationException.Reason.INVALID_FLYOVER_DERIVATION_HASH; import static java.util.Objects.isNull; public class FlyoverRedeemScriptBuilderImpl implements FlyoverRedeemScriptBuilder { @@ -29,7 +29,7 @@ private void validateFlyoverDerivationHash(Keccak256 flyoverDerivationHash) { if (isNull(flyoverDerivationHash) || flyoverDerivationHash.equals(Keccak256.ZERO_HASH)) { String message = String.format("Provided flyover derivation hash %s is invalid.", flyoverDerivationHash); logger.warn("[validateFlyoverDerivationHash] {}", message); - throw new FlyoverRedeemScriptCreationException(message, INVALID_FLYOVER_DERIVATION_HASH); + throw new RedeemScriptCreationException(message, INVALID_FLYOVER_DERIVATION_HASH); } } } diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java deleted file mode 100644 index 543bab0be7e..00000000000 --- a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptCreationException.java +++ /dev/null @@ -1,17 +0,0 @@ -package co.rsk.peg.bitcoin; - -public class FlyoverRedeemScriptCreationException extends RuntimeException { - private final Reason reason; - - public enum Reason { - INVALID_FLYOVER_DERIVATION_HASH - } - - public FlyoverRedeemScriptCreationException(String s, Reason reason) { - super(s); - this.reason = reason; - } - - public Reason getReason() { return reason; } - -} diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/RedeemScriptCreationException.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/RedeemScriptCreationException.java index ba90caa3a5e..a35c51a7b56 100644 --- a/rskj-core/src/main/java/co/rsk/peg/bitcoin/RedeemScriptCreationException.java +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/RedeemScriptCreationException.java @@ -5,7 +5,8 @@ public class RedeemScriptCreationException extends RuntimeException { public enum Reason { INVALID_INTERNAL_REDEEM_SCRIPTS, - INVALID_CSV_VALUE + INVALID_CSV_VALUE, + INVALID_FLYOVER_DERIVATION_HASH } public RedeemScriptCreationException(String s, Reason reason) { diff --git a/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java b/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java index ce41ba00b23..a06607f959a 100644 --- a/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.stream.Stream; -import static co.rsk.peg.bitcoin.FlyoverRedeemScriptCreationException.Reason.INVALID_FLYOVER_DERIVATION_HASH; +import static co.rsk.peg.bitcoin.RedeemScriptCreationException.Reason.INVALID_FLYOVER_DERIVATION_HASH; import static org.junit.jupiter.api.Assertions.*; class FlyoverRedeemScriptBuilderImplTest { @@ -32,7 +32,7 @@ void setUp() { @ParameterizedTest @MethodSource("invalidDerivationHashArgsProvider") void addFlyoverDerivationHashToRedeemScript_withInvalidPrefix_shouldThrowFlyoverRedeemScriptCreationException(Keccak256 flyoverDerivationHash) { - FlyoverRedeemScriptCreationException exception = assertThrows(FlyoverRedeemScriptCreationException.class, + RedeemScriptCreationException exception = assertThrows(RedeemScriptCreationException.class, () -> flyoverRedeemScriptBuilder.addFlyoverDerivationHashToRedeemScript(flyoverDerivationHash, redeemScript)); assertEquals(INVALID_FLYOVER_DERIVATION_HASH, exception.getReason()); From e90a050d68e54b0c0feadfd47094566e0f431d90 Mon Sep 17 00:00:00 2001 From: Marcos Date: Fri, 13 Sep 2024 12:50:18 -0300 Subject: [PATCH 3/6] Change call to P2shErpFederationBuilder --- .../co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java b/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java index a06607f959a..2a1d3562823 100644 --- a/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImplTest.java @@ -24,7 +24,7 @@ class FlyoverRedeemScriptBuilderImplTest { @BeforeEach void setUp() { - Federation federation = new P2shErpFederationBuilder().build(); + Federation federation = P2shErpFederationBuilder.builder().build(); redeemScript = federation.getRedeemScript(); flyoverRedeemScriptBuilder = new FlyoverRedeemScriptBuilderImpl(); } From 2be66e43f284b997c3bdb425506352e27d996eaf Mon Sep 17 00:00:00 2001 From: Marcos Date: Wed, 28 Aug 2024 11:49:48 -0300 Subject: [PATCH 4/6] Add @Override annotation --- .../main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java | 1 - .../java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java index 6eb34fab9b9..b7c120f8c03 100644 --- a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilder.java @@ -5,5 +5,4 @@ public interface FlyoverRedeemScriptBuilder { Script addFlyoverDerivationHashToRedeemScript(Keccak256 flyoverDerivationHash, Script redeemScript); - } diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java index abb49055532..82df1aa5846 100644 --- a/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/FlyoverRedeemScriptBuilderImpl.java @@ -13,6 +13,7 @@ public class FlyoverRedeemScriptBuilderImpl implements FlyoverRedeemScriptBuilder { private static final Logger logger = LoggerFactory.getLogger(FlyoverRedeemScriptBuilderImpl.class); + @Override public Script addFlyoverDerivationHashToRedeemScript(Keccak256 flyoverDerivationHash, Script redeemScript) { validateFlyoverDerivationHash(flyoverDerivationHash); From 7719ed10ac4d597801d76ef4615c1957addb451d Mon Sep 17 00:00:00 2001 From: Marcos Date: Tue, 17 Sep 2024 10:28:32 -0300 Subject: [PATCH 5/6] Refactor redeem script builders to use 'of' method name --- .../java/co/rsk/peg/bitcoin/BitcoinUtils.java | 7 ++-- .../peg/bitcoin/ErpRedeemScriptBuilder.java | 14 ++++---- .../bitcoin/ErpRedeemScriptBuilderUtils.java | 15 ++++---- .../bitcoin/FlyoverRedeemScriptBuilder.java | 2 +- .../FlyoverRedeemScriptBuilderImpl.java | 9 ++--- .../NonStandardErpRedeemScriptBuilder.java | 34 ++++++++++--------- ...StandardErpRedeemScriptBuilderFactory.java | 5 +-- ...andardErpRedeemScriptBuilderHardcoded.java | 16 ++++----- ...pRedeemScriptBuilderWithCsvUnsignedBE.java | 30 ++++++++-------- .../bitcoin/P2shErpRedeemScriptBuilder.java | 24 +++++++------ .../co/rsk/peg/federation/ErpFederation.java | 6 ++-- .../FlyoverRedeemScriptBuilderImplTest.java | 4 +-- .../NonStandardErpFederationsTest.java | 16 ++++----- .../peg/federation/P2shErpFederationTest.java | 10 +++--- 14 files changed, 96 insertions(+), 96 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/peg/bitcoin/BitcoinUtils.java b/rskj-core/src/main/java/co/rsk/peg/bitcoin/BitcoinUtils.java index f23537a9e05..1bf670b7af3 100644 --- a/rskj-core/src/main/java/co/rsk/peg/bitcoin/BitcoinUtils.java +++ b/rskj-core/src/main/java/co/rsk/peg/bitcoin/BitcoinUtils.java @@ -25,13 +25,10 @@ public static Optional getFirstInputSigHash(BtcTransaction btcTx){ } TransactionInput txInput = btcTx.getInput(FIRST_INPUT_INDEX); Optional