From e547d5549380c7921db073e8773d5add67da9a3c Mon Sep 17 00:00:00 2001 From: julia-zack Date: Thu, 30 Jan 2025 11:20:21 -0300 Subject: [PATCH 1/2] Create new p2sh-p2wsh fed format version. Build new p2sh-p2wsh fed type in fed factory --- .../rsk/peg/federation/FederationFactory.java | 16 ++ .../federation/FederationFormatVersion.java | 3 +- .../peg/federation/FederationFactoryTest.java | 161 +++++++++++------- 3 files changed, 116 insertions(+), 64 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/peg/federation/FederationFactory.java b/rskj-core/src/main/java/co/rsk/peg/federation/FederationFactory.java index 7a55bf916a1..ed71226ff93 100644 --- a/rskj-core/src/main/java/co/rsk/peg/federation/FederationFactory.java +++ b/rskj-core/src/main/java/co/rsk/peg/federation/FederationFactory.java @@ -56,4 +56,20 @@ public static ErpFederation buildP2shErpFederation( P2SH_ERP_FEDERATION.getFormatVersion() ); } + + public static ErpFederation buildP2shP2wshErpFederation( + FederationArgs federationArgs, + List erpPubKeys, + long activationDelay + ) { + ErpRedeemScriptBuilder erpRedeemScriptBuilder = P2shErpRedeemScriptBuilder.builder(); + + return new ErpFederation( + federationArgs, + erpPubKeys, + activationDelay, + erpRedeemScriptBuilder, + P2SH_P2WSH_ERP_FEDERATION.getFormatVersion() + ); + } } diff --git a/rskj-core/src/main/java/co/rsk/peg/federation/FederationFormatVersion.java b/rskj-core/src/main/java/co/rsk/peg/federation/FederationFormatVersion.java index 43b942716b6..5eae68d0af1 100644 --- a/rskj-core/src/main/java/co/rsk/peg/federation/FederationFormatVersion.java +++ b/rskj-core/src/main/java/co/rsk/peg/federation/FederationFormatVersion.java @@ -3,7 +3,8 @@ public enum FederationFormatVersion { STANDARD_MULTISIG_FEDERATION(1000), NON_STANDARD_ERP_FEDERATION(2000), - P2SH_ERP_FEDERATION(3000); + P2SH_ERP_FEDERATION(3000), + P2SH_P2WSH_ERP_FEDERATION(4000); private int version; diff --git a/rskj-core/src/test/java/co/rsk/peg/federation/FederationFactoryTest.java b/rskj-core/src/test/java/co/rsk/peg/federation/FederationFactoryTest.java index 5bf92ff64ad..abd37a65837 100644 --- a/rskj-core/src/test/java/co/rsk/peg/federation/FederationFactoryTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/federation/FederationFactoryTest.java @@ -7,6 +7,7 @@ import co.rsk.peg.federation.constants.FederationTestNetConstants; import org.bouncycastle.util.encoders.Hex; import org.ethereum.config.blockchain.upgrades.ActivationConfig; +import org.ethereum.config.blockchain.upgrades.ActivationConfigsForTest; import org.ethereum.config.blockchain.upgrades.ConsensusRule; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -21,42 +22,40 @@ import static co.rsk.peg.federation.FederationFormatVersion.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class FederationFactoryTest { + private static final BtcECKey federator0PublicKey = BtcECKey.fromPublicOnly(Hex.decode("03b53899c390573471ba30e5054f78376c5f797fda26dde7a760789f02908cbad2")); + private static final BtcECKey federator1PublicKey = BtcECKey.fromPublicOnly(Hex.decode("027319afb15481dbeb3c426bcc37f9a30e7f51ceff586936d85548d9395bcc2344")); + private static final BtcECKey federator2PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0355a2e9bf100c00fc0a214afd1bf272647c7824eb9cb055480962f0c382596a70")); + private static final BtcECKey federator3PublicKey = BtcECKey.fromPublicOnly(Hex.decode("02566d5ded7c7db1aa7ee4ef6f76989fb42527fcfdcddcd447d6793b7d869e46f7")); + private static final BtcECKey federator4PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0294c817150f78607566e961b3c71df53a22022a80acbb982f83c0c8baac040adc")); + private static final BtcECKey federator5PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0372cd46831f3b6afd4c044d160b7667e8ebf659d6cb51a825a3104df6ee0638c6")); + private static final BtcECKey federator6PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0340df69f28d69eef60845da7d81ff60a9060d4da35c767f017b0dd4e20448fb44")); + private static final BtcECKey federator7PublicKey = BtcECKey.fromPublicOnly(Hex.decode("02ac1901b6fba2c1dbd47d894d2bd76c8ba1d296d65f6ab47f1c6b22afb53e73eb")); + private static final BtcECKey federator8PublicKey = BtcECKey.fromPublicOnly(Hex.decode("031aabbeb9b27258f98c2bf21f36677ae7bae09eb2d8c958ef41a20a6e88626d26")); + private static final BtcECKey federator9PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0245ef34f5ee218005c9c21227133e8568a4f3f11aeab919c66ff7b816ae1ffeea")); + private static final List defaultKeys = Arrays.asList( + federator0PublicKey, federator1PublicKey, federator2PublicKey, + federator3PublicKey, federator4PublicKey, federator5PublicKey, + federator6PublicKey, federator7PublicKey, federator8PublicKey, + federator9PublicKey + ); + private static final List federationMembers = FederationTestUtils.getFederationMembersWithKeys(defaultKeys); + private static final Instant creationTime = ZonedDateTime.parse("2017-06-10T02:30:00Z").toInstant(); + private static final long creationBlockNumber = 0L; + private FederationConstants federationConstants; private NetworkParameters networkParameters; - private List federationMembers; - private Instant creationTime; - private long creationBlockNumber; private List emergencyKeys; private long activationDelayValue; private ActivationConfig.ForBlock activations; @BeforeEach void setUp() { - BtcECKey federator0PublicKey = BtcECKey.fromPublicOnly(Hex.decode("03b53899c390573471ba30e5054f78376c5f797fda26dde7a760789f02908cbad2")); - BtcECKey federator1PublicKey = BtcECKey.fromPublicOnly(Hex.decode("027319afb15481dbeb3c426bcc37f9a30e7f51ceff586936d85548d9395bcc2344")); - BtcECKey federator2PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0355a2e9bf100c00fc0a214afd1bf272647c7824eb9cb055480962f0c382596a70")); - BtcECKey federator3PublicKey = BtcECKey.fromPublicOnly(Hex.decode("02566d5ded7c7db1aa7ee4ef6f76989fb42527fcfdcddcd447d6793b7d869e46f7")); - BtcECKey federator4PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0294c817150f78607566e961b3c71df53a22022a80acbb982f83c0c8baac040adc")); - BtcECKey federator5PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0372cd46831f3b6afd4c044d160b7667e8ebf659d6cb51a825a3104df6ee0638c6")); - BtcECKey federator6PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0340df69f28d69eef60845da7d81ff60a9060d4da35c767f017b0dd4e20448fb44")); - BtcECKey federator7PublicKey = BtcECKey.fromPublicOnly(Hex.decode("02ac1901b6fba2c1dbd47d894d2bd76c8ba1d296d65f6ab47f1c6b22afb53e73eb")); - BtcECKey federator8PublicKey = BtcECKey.fromPublicOnly(Hex.decode("031aabbeb9b27258f98c2bf21f36677ae7bae09eb2d8c958ef41a20a6e88626d26")); - BtcECKey federator9PublicKey = BtcECKey.fromPublicOnly(Hex.decode("0245ef34f5ee218005c9c21227133e8568a4f3f11aeab919c66ff7b816ae1ffeea")); - List defaultKeys = Arrays.asList( - federator0PublicKey, federator1PublicKey, federator2PublicKey, - federator3PublicKey, federator4PublicKey, federator5PublicKey, - federator6PublicKey, federator7PublicKey, federator8PublicKey, - federator9PublicKey - ); - federationMembers = FederationTestUtils.getFederationMembersWithKeys(defaultKeys); - creationTime = ZonedDateTime.parse("2017-06-10T02:30:00Z").toInstant(); - creationBlockNumber = 0L; federationConstants = FederationMainNetConstants.getInstance(); networkParameters = federationConstants.getBtcParams(); + activations = ActivationConfigsForTest.all().forBlock(0L); } @Test @@ -67,6 +66,17 @@ void buildStandardMultiSigFederation() { assertEquals(STANDARD_MULTISIG_FEDERATION.getFormatVersion(), version); } + private Federation createStandardMultisigFederation() { + FederationArgs federationArgs = new FederationArgs( + federationMembers, + creationTime, + creationBlockNumber, + networkParameters + ); + + return FederationFactory.buildStandardMultiSigFederation(federationArgs); + } + @Nested @Tag("erpFeds") class ErpFederationTests { @@ -74,7 +84,6 @@ class ErpFederationTests { void setUp() { emergencyKeys = federationConstants.getErpFedPubKeysList(); activationDelayValue = federationConstants.getErpFedActivationDelay(); - activations = mock(ActivationConfig.ForBlock.class); } @Test @@ -95,23 +104,24 @@ void differentNonStandardErpFederations_areNotEqualFeds_butHaveSameNonStandardFe int version; - // in testnet it should build non standard hardcoded fed - when(activations.isActive(ConsensusRule.RSKIP201)).thenReturn(true); + // in testnet it should build non-standard hardcoded fed + activations = ActivationConfigsForTest.iris300().forBlock(0L); ErpFederation federationPostRSKIP201 = createNonStandardErpFederation(); version = federationPostRSKIP201.getFormatVersion(); assertEquals(NON_STANDARD_ERP_FEDERATION.getFormatVersion(), version); - // build non standard fed with csv unsigned big endian - when(activations.isActive(ConsensusRule.RSKIP284)).thenReturn(true); + // build non-standard fed with csv unsigned big endian + List exceptedRSKIP = List.of(ConsensusRule.RSKIP293); + activations = ActivationConfigsForTest.hop400(exceptedRSKIP).forBlock(0L); ErpFederation federationPostRSKIP284 = createNonStandardErpFederation(); version = federationPostRSKIP284.getFormatVersion(); assertEquals(NON_STANDARD_ERP_FEDERATION.getFormatVersion(), version); assertNotEquals(federationPostRSKIP201, federationPostRSKIP284); - // build non standard fed - when(activations.isActive(ConsensusRule.RSKIP293)).thenReturn(true); + // build non-standard fed + activations = ActivationConfigsForTest.hop400().forBlock(0L); ErpFederation federationPostRSKIP293 = createNonStandardErpFederation(); version = federationPostRSKIP293.getFormatVersion(); @@ -124,23 +134,24 @@ void differentNonStandardErpFederations_areNotEqualFeds_butHaveSameNonStandardFe void differentNonStandardErpFederations_areNotEqualFeds_butHaveSameNonStandardFedFormat_mainnet() { int version; - // in mainnet it should build non standard fed with csv unsigned big endian - when(activations.isActive(ConsensusRule.RSKIP201)).thenReturn(true); + // in mainnet it should build non-standard fed with csv unsigned big endian + activations = ActivationConfigsForTest.iris300().forBlock(0L); ErpFederation federationPostRSKIP201 = createNonStandardErpFederation(); version = federationPostRSKIP201.getFormatVersion(); assertEquals(NON_STANDARD_ERP_FEDERATION.getFormatVersion(), version); - // should build non standard fed with csv unsigned big endian - when(activations.isActive(ConsensusRule.RSKIP284)).thenReturn(true); + // should build non-standard fed with csv unsigned big endian + List exceptedRSKIP = List.of(ConsensusRule.RSKIP293); + activations = ActivationConfigsForTest.hop400(exceptedRSKIP).forBlock(0L); ErpFederation federationPostRSKIP284 = createNonStandardErpFederation(); version = federationPostRSKIP284.getFormatVersion(); assertEquals(NON_STANDARD_ERP_FEDERATION.getFormatVersion(), version); assertEquals(federationPostRSKIP201, federationPostRSKIP284); - // build non standard fed - when(activations.isActive(ConsensusRule.RSKIP293)).thenReturn(true); + // build non-standard fed + activations = ActivationConfigsForTest.hop400().forBlock(0L); ErpFederation federationPostRSKIP293 = createNonStandardErpFederation(); version = federationPostRSKIP293.getFormatVersion(); @@ -166,38 +177,62 @@ void p2shErpFederation_haveP2shFedFormat() { version = federation.getFormatVersion(); assertEquals(P2SH_ERP_FEDERATION.getFormatVersion(), version); } - } - private Federation createStandardMultisigFederation() { - FederationArgs federationArgs = new FederationArgs( - federationMembers, - creationTime, - creationBlockNumber, - networkParameters - ); + private ErpFederation createNonStandardErpFederation() { + FederationArgs federationArgs = new FederationArgs( + federationMembers, + creationTime, + creationBlockNumber, + networkParameters + ); - return FederationFactory.buildStandardMultiSigFederation(federationArgs); - } + return FederationFactory.buildNonStandardErpFederation(federationArgs, emergencyKeys, activationDelayValue, activations); + } - private ErpFederation createNonStandardErpFederation() { - FederationArgs federationArgs = new FederationArgs( - federationMembers, - creationTime, - creationBlockNumber, - networkParameters - ); + private ErpFederation createP2shErpFederation() { + FederationArgs federationArgs = new FederationArgs( + federationMembers, + creationTime, + creationBlockNumber, + networkParameters + ); - return FederationFactory.buildNonStandardErpFederation(federationArgs, emergencyKeys, activationDelayValue, activations); - } + return FederationFactory.buildP2shErpFederation(federationArgs, emergencyKeys, activationDelayValue); + } - private ErpFederation createP2shErpFederation() { - FederationArgs federationArgs = new FederationArgs( - federationMembers, - creationTime, - creationBlockNumber, - networkParameters - ); + @Test + void p2shP2wshErpFederation_mainnet_hasP2shP2wshFedFormat() { + // act + ErpFederation federation = createP2shP2wshErpFederation(); + + // assert + int expectedVersion = P2SH_P2WSH_ERP_FEDERATION.getFormatVersion(); + assertEquals(expectedVersion, federation.getFormatVersion()); + } + + @Test + void p2shP2wshErpFederation_testnet_hasP2shP2wshFedFormat() { + // arrange + federationConstants = FederationTestNetConstants.getInstance(); + networkParameters = federationConstants.getBtcParams(); + + // act + ErpFederation federation = createP2shP2wshErpFederation(); + + // assert + int expectedVersion = P2SH_P2WSH_ERP_FEDERATION.getFormatVersion(); + assertEquals(expectedVersion, federation.getFormatVersion()); + } + + private ErpFederation createP2shP2wshErpFederation() { + FederationArgs federationArgs = new FederationArgs( + federationMembers, + creationTime, + creationBlockNumber, + networkParameters + ); - return FederationFactory.buildP2shErpFederation(federationArgs, emergencyKeys, activationDelayValue); + return FederationFactory.buildP2shP2wshErpFederation(federationArgs, emergencyKeys, activationDelayValue); + } } } From d3f6809714d7b501717e961cd78c6e475d1927ab Mon Sep 17 00:00:00 2001 From: julia-zack Date: Thu, 30 Jan 2025 11:34:07 -0300 Subject: [PATCH 2/2] Create p2sh-p2wsh erp federation builder --- .../P2shP2wshErpFederationBuilder.java | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 rskj-core/src/test/java/co/rsk/peg/federation/P2shP2wshErpFederationBuilder.java diff --git a/rskj-core/src/test/java/co/rsk/peg/federation/P2shP2wshErpFederationBuilder.java b/rskj-core/src/test/java/co/rsk/peg/federation/P2shP2wshErpFederationBuilder.java new file mode 100644 index 00000000000..f64b65300d3 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/peg/federation/P2shP2wshErpFederationBuilder.java @@ -0,0 +1,115 @@ +package co.rsk.peg.federation; + +import co.rsk.bitcoinj.core.BtcECKey; +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.bitcoin.BitcoinTestUtils; +import co.rsk.peg.federation.constants.FederationMainNetConstants; +import org.ethereum.crypto.ECKey; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +public class P2shP2wshErpFederationBuilder { + private List membersBtcPublicKeys; + private List membersRskPublicKeys; + private List membersMstPublicKeys; + private List erpPublicKeys; + private long erpActivationDelay; + private Instant creationTime; + private long creationBlockNumber; + private NetworkParameters networkParameters; + + private P2shP2wshErpFederationBuilder() { + this.membersBtcPublicKeys = BitcoinTestUtils.getBtcEcKeysFromSeeds(new String[]{ + "member01", + "member02", + "member03", + "member04", + "member05", + "member06", + "member07", + "member08", + "member09" + }, true); + this.membersRskPublicKeys = new ArrayList<>(); + this.membersMstPublicKeys = new ArrayList<>(); + this.erpPublicKeys = FederationMainNetConstants.getInstance().getErpFedPubKeysList(); + this.erpActivationDelay = 52_560L; + this.creationTime = Instant.ofEpochSecond(100_000_000L); + this.creationBlockNumber = 1L; + this.networkParameters = NetworkParameters.fromID(NetworkParameters.ID_MAINNET); + } + + public static P2shP2wshErpFederationBuilder builder() { + return new P2shP2wshErpFederationBuilder(); + } + + public P2shP2wshErpFederationBuilder withMembersBtcPublicKeys(List btcPublicKeys) { + this.membersBtcPublicKeys = btcPublicKeys; + return this; + } + + public P2shP2wshErpFederationBuilder withMembersRskPublicKeys(List rskPublicKeys) { + this.membersRskPublicKeys = rskPublicKeys; + return this; + } + + public P2shP2wshErpFederationBuilder withMembersMstPublicKeys(List mstPublicKeys) { + this.membersMstPublicKeys = mstPublicKeys; + return this; + } + + public P2shP2wshErpFederationBuilder withErpPublicKeys(List erpPublicKeys) { + this.erpPublicKeys = erpPublicKeys; + return this; + } + + public P2shP2wshErpFederationBuilder withErpActivationDelay(long erpActivationDelay) { + this.erpActivationDelay = erpActivationDelay; + return this; + } + + public P2shP2wshErpFederationBuilder withCreationTime(Instant creationTime) { + this.creationTime = creationTime; + return this; + } + + public P2shP2wshErpFederationBuilder withCreationBlockNumber(long creationBlockNumber) { + this.creationBlockNumber = creationBlockNumber; + return this; + } + + public P2shP2wshErpFederationBuilder withNetworkParameters(NetworkParameters networkParameters) { + this.networkParameters = networkParameters; + return this; + } + + public ErpFederation build() { + List federationMembers = getFederationMembers(); + FederationArgs federationArgs = new FederationArgs(federationMembers, creationTime, creationBlockNumber, networkParameters); + + return FederationFactory.buildP2shP2wshErpFederation(federationArgs, erpPublicKeys, erpActivationDelay); + } + + private List getFederationMembers() { + if (membersRskPublicKeys.isEmpty()) { + this.membersRskPublicKeys = membersBtcPublicKeys.stream() + .map(BtcECKey::getPubKey) + .map(ECKey::fromPublicOnly) + .toList(); + } + + if (membersMstPublicKeys.isEmpty()) { + this.membersMstPublicKeys = new ArrayList<>(membersRskPublicKeys); + } + + return IntStream.range(0, membersBtcPublicKeys.size()) + .mapToObj(i -> new FederationMember( + membersBtcPublicKeys.get(i), + membersRskPublicKeys.get(i), + membersMstPublicKeys.get(i))) + .toList(); + } +}