Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create p2sh-p2wsh erp federation builder #2971

Draft
wants to merge 2 commits into
base: add_p2shp2wsh_fed_type_to_fed_factory
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,20 @@ public static ErpFederation buildP2shErpFederation(
P2SH_ERP_FEDERATION.getFormatVersion()
);
}

public static ErpFederation buildP2shP2wshErpFederation(
FederationArgs federationArgs,
List<BtcECKey> erpPubKeys,
long activationDelay
) {
ErpRedeemScriptBuilder erpRedeemScriptBuilder = P2shErpRedeemScriptBuilder.builder();

return new ErpFederation(
federationArgs,
erpPubKeys,
activationDelay,
erpRedeemScriptBuilder,
P2SH_P2WSH_ERP_FEDERATION.getFormatVersion()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<BtcECKey> defaultKeys = Arrays.asList(
federator0PublicKey, federator1PublicKey, federator2PublicKey,
federator3PublicKey, federator4PublicKey, federator5PublicKey,
federator6PublicKey, federator7PublicKey, federator8PublicKey,
federator9PublicKey
);
private static final List<FederationMember> 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<FederationMember> federationMembers;
private Instant creationTime;
private long creationBlockNumber;
private List<BtcECKey> 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<BtcECKey> 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
Expand All @@ -67,14 +66,24 @@ 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 {
@BeforeEach
void setUp() {
emergencyKeys = federationConstants.getErpFedPubKeysList();
activationDelayValue = federationConstants.getErpFedActivationDelay();
activations = mock(ActivationConfig.ForBlock.class);
}

@Test
Expand All @@ -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<ConsensusRule> 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();

Expand All @@ -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<ConsensusRule> 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();

Expand All @@ -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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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<BtcECKey> membersBtcPublicKeys;
private List<ECKey> membersRskPublicKeys;
private List<ECKey> membersMstPublicKeys;
private List<BtcECKey> 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<BtcECKey> btcPublicKeys) {
this.membersBtcPublicKeys = btcPublicKeys;
return this;
}

public P2shP2wshErpFederationBuilder withMembersRskPublicKeys(List<ECKey> rskPublicKeys) {
this.membersRskPublicKeys = rskPublicKeys;
return this;
}

public P2shP2wshErpFederationBuilder withMembersMstPublicKeys(List<ECKey> mstPublicKeys) {
this.membersMstPublicKeys = mstPublicKeys;
return this;
}

public P2shP2wshErpFederationBuilder withErpPublicKeys(List<BtcECKey> 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<FederationMember> federationMembers = getFederationMembers();
FederationArgs federationArgs = new FederationArgs(federationMembers, creationTime, creationBlockNumber, networkParameters);

return FederationFactory.buildP2shP2wshErpFederation(federationArgs, erpPublicKeys, erpActivationDelay);
}

private List<FederationMember> 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();
}
}
Loading