Skip to content

Commit

Permalink
Merge branch 'master' into ARROWHEAD-6.5.1-rc-master-merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Vovchyk authored Jan 27, 2025
2 parents f75766e + ef047fd commit e5982c8
Show file tree
Hide file tree
Showing 158 changed files with 21,082 additions and 3,823 deletions.
10 changes: 5 additions & 5 deletions gradle/verification-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@
<sha256 value="c717c468bfc91536f1dbc0d98d6116a8e7c49fbaff643ef8710e7505cc450878" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="co.rsk.bitcoinj" name="bitcoinj-thin" version="0.14.4-rsk-16">
<artifact name="bitcoinj-thin-0.14.4-rsk-16.jar">
<sha256 value="53957d6941a882f7aa33188da3dadcf96f15fa2ffd62e9130937eb84e98f11a4" origin="Generated by Gradle"/>
<component group="co.rsk.bitcoinj" name="bitcoinj-thin" version="0.14.4-rsk-17">
<artifact name="bitcoinj-thin-0.14.4-rsk-17.jar">
<sha256 value="beff6002e72162984daa3e7016b1a6fb6d372e5cfb14101a50d150c0adfbda71" origin="Generated by Gradle"/>
</artifact>
<artifact name="bitcoinj-thin-0.14.4-rsk-16.pom">
<sha256 value="ea7726838385d7694f63622398d871b92a247b83418fe4d6cb9c6f3d5991fd3a" origin="Generated by Gradle"/>
<artifact name="bitcoinj-thin-0.14.4-rsk-17.pom">
<sha256 value="32fca4aac555f60d824cda58f69e64a7641f60dbbf5ec733966dbe2ded3214d7" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.diffplug.durian" name="durian-collect" version="1.2.0">
Expand Down
2 changes: 1 addition & 1 deletion rskj-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ ext {
jaxwsRtVer : '2.3.5',
picocliVer : '4.6.3',

bitcoinjThinVer: '0.14.4-rsk-16',
bitcoinjThinVer: '0.14.4-rsk-17',
rskjNativeVer: '1.3.0',
]

Expand Down
6 changes: 3 additions & 3 deletions rskj-core/src/jmh/resources/conf/testnet-3_860_000.conf
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ sendRawTransaction.tx=0xf868826d28840387ee40825208947986b3df570230288501eea3d890
############################
# estimateGas
############################
estimateGas.from=0x05EEEF8B42D583880A24d74853669ee4a36bB530
estimateGas.to=0x51B631722323189ee8d3e4E558eC399d7aa40FcC
estimateGas.data=0xcbf83a0400000000000000000000000000000000000000000000000000000000000000034254435553440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000409c969dacf4b38000000000000000000000000000005eeef8b42d583880a24d74853669ee4a36bb53000000000000000000000000000000000000000000000000000000000003567dd0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000038e9c434a2b164e2c07758f0b30af4cf4b5ad0dc98e8f13413b8beb36124574b82c84681feac9d982591f4701ba33e2949d1ae0df7363ac90d99d5c16f91a9f0c6c1131f84944ae1dd2bba3bbcf3e592a838286bbcf816247939548ee33ec23e200000000000000000000000000000000000000000000000000000000000000034821d173b4098826fb4d5a42dbfd4582de9ff98efabecb5596ac088ec387e9c765a5d167455ef2de2636857fde728c153e94e6406779063f6d95f76a85a07ef33a0ab20a151a912a49838ad9262524986595531bc0680a502ca04fe736414775
estimateGas.from=0x824dB056754BE52602CF9a2Ea1b8082Dad4dc89C
estimateGas.to=0xB913c7494b918Ed637D4df1308E1B7FF820b75B6
estimateGas.data=0x5a686699000000000000000000000000000000000000000000000000f438a7c30553000000000000000000000000000000000000000000000000000000000000645fa03b0000000000000000000000006951020041bfa2565877bf0eaf7f5df039b490dc

############################
# debug
Expand Down
224 changes: 210 additions & 14 deletions rskj-core/src/main/java/co/rsk/peg/Bridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package co.rsk.peg;

import static co.rsk.peg.BridgeSerializationUtils.deserializeRskTxHash;
import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP417;

import co.rsk.bitcoinj.core.*;
Expand All @@ -33,6 +34,7 @@
import co.rsk.peg.vote.ABICallSpec;
import co.rsk.peg.bitcoin.MerkleBranch;
import co.rsk.peg.federation.Federation;
import co.rsk.peg.federation.FederationChangeResponseCode;
import co.rsk.peg.federation.FederationMember;
import co.rsk.peg.flyover.FlyoverTxResponseCodes;
import co.rsk.peg.utils.BtcTransactionFormatUtils;
Expand Down Expand Up @@ -95,6 +97,8 @@ public class Bridge extends PrecompiledContracts.PrecompiledContract {
public static final CallTransaction.Function ADD_SIGNATURE = BridgeMethods.ADD_SIGNATURE.getFunction();
// Returns a StateForFederator encoded in RLP
public static final CallTransaction.Function GET_STATE_FOR_BTC_RELEASE_CLIENT = BridgeMethods.GET_STATE_FOR_BTC_RELEASE_CLIENT.getFunction();
// Returns a StateForProposedFederator encoded in RLP
public static final CallTransaction.Function GET_STATE_FOR_SVP_CLIENT = BridgeMethods.GET_STATE_FOR_SVP_CLIENT.getFunction();
// Returns a BridgeState encoded in RLP
public static final CallTransaction.Function GET_STATE_FOR_DEBUGGING = BridgeMethods.GET_STATE_FOR_DEBUGGING.getFunction();
// Return the bitcoin blockchain best chain height know by the bridge contract
Expand Down Expand Up @@ -152,6 +156,17 @@ public class Bridge extends PrecompiledContracts.PrecompiledContract {
// Returns the block number of the creation of the retiring federation
public static final CallTransaction.Function GET_RETIRING_FEDERATION_CREATION_BLOCK_NUMBER = BridgeMethods.GET_RETIRING_FEDERATION_CREATION_BLOCK_NUMBER.getFunction();

// Returns the proposed federation bitcoin address
public static final CallTransaction.Function GET_PROPOSED_FEDERATION_ADDRESS = BridgeMethods.GET_PROPOSED_FEDERATION_ADDRESS.getFunction();
// Returns the number of federates in the proposed federation
public static final CallTransaction.Function GET_PROPOSED_FEDERATION_SIZE = BridgeMethods.GET_PROPOSED_FEDERATION_SIZE.getFunction();
// Returns the public key of given type the federator at the specified index for the current proposed federation
public static final CallTransaction.Function GET_PROPOSED_FEDERATOR_PUBLIC_KEY_OF_TYPE = BridgeMethods.GET_PROPOSED_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction();
// Returns the creation time of the proposed federation
public static final CallTransaction.Function GET_PROPOSED_FEDERATION_CREATION_TIME = BridgeMethods.GET_PROPOSED_FEDERATION_CREATION_TIME.getFunction();
// Returns the block number of the creation of the proposed federation
public static final CallTransaction.Function GET_PROPOSED_FEDERATION_CREATION_BLOCK_NUMBER = BridgeMethods.GET_PROPOSED_FEDERATION_CREATION_BLOCK_NUMBER.getFunction();

// Creates a new pending federation and returns its id
public static final CallTransaction.Function CREATE_FEDERATION = BridgeMethods.CREATE_FEDERATION.getFunction();
// Adds the given key to the current pending federation
Expand Down Expand Up @@ -614,14 +629,15 @@ public void addSignature(Object[] args) throws VMException {
}
signatures.add(signatureByteArray);
}
byte[] rskTxHash = (byte[]) args[2];
if (rskTxHash.length!=32) {
throw new BridgeIllegalArgumentException("Invalid rsk tx hash " + Bytes.of(rskTxHash));
byte[] rskTxHashSerialized = (byte[]) args[2];
Keccak256 rskTxHash;
try {
rskTxHash = deserializeRskTxHash(rskTxHashSerialized);
} catch (IllegalArgumentException e) {
throw new BridgeIllegalArgumentException("Invalid rsk tx hash " + Bytes.of(rskTxHashSerialized));
}
try {
bridgeSupport.addSignature(federatorPublicKey, signatures, rskTxHash);
} catch (BridgeIllegalArgumentException e) {
throw e;
} catch (Exception e) {
logger.warn("Exception in addSignature", e);
throw new VMException("Exception in addSignature", e);
Expand All @@ -639,6 +655,17 @@ public byte[] getStateForBtcReleaseClient(Object[] args) throws VMException {
}
}

public byte[] getStateForSvpClient(Object[] args) throws VMException {
logger.trace("getStateForSvpClient");

try {
return bridgeSupport.getStateForSvpClient();
} catch (Exception e) {
logger.warn("Exception in getStateForSvpClient", e);
throw new VMException("Exception in getStateForSvpClient", e);
}
}

public byte[] getStateForDebugging(Object[] args) throws VMException {
logger.trace("getStateForDebugging");

Expand Down Expand Up @@ -812,9 +839,15 @@ public byte[] getFederatorPublicKeyOfType(Object[] args) throws VMException {

public Long getFederationCreationTime(Object[] args) {
logger.trace("getFederationCreationTime");
Instant activeFederationCreationTime = bridgeSupport.getActiveFederationCreationTime();

// Return the creation time in milliseconds from the epoch
return bridgeSupport.getActiveFederationCreationTime().toEpochMilli();
if (!activations.isActive(ConsensusRule.RSKIP419)) {
// Return the creation time in milliseconds from the epoch
return activeFederationCreationTime.toEpochMilli();
}

// Return the creation time in seconds from the epoch
return activeFederationCreationTime.getEpochSecond();
}

public long getFederationCreationBlockNumber(Object[] args) {
Expand Down Expand Up @@ -887,15 +920,20 @@ public byte[] getRetiringFederatorPublicKeyOfType(Object[] args) throws VMExcept
public Long getRetiringFederationCreationTime(Object[] args) {
logger.trace("getRetiringFederationCreationTime");

Instant creationTime = bridgeSupport.getRetiringFederationCreationTime();
Instant retiringFederationCreationTime = bridgeSupport.getRetiringFederationCreationTime();

if (creationTime == null) {
if (retiringFederationCreationTime == null) {
// -1 is returned when no retiring federation
return -1L;
}

// Return the creation time in milliseconds from the epoch
return creationTime.toEpochMilli();
if (!activations.isActive(ConsensusRule.RSKIP419)) {
// Return the creation time in milliseconds from the epoch
return retiringFederationCreationTime.toEpochMilli();
}

// Return the creation time in seconds from the epoch
return retiringFederationCreationTime.getEpochSecond();
}

public long getRetiringFederationCreationBlockNumber(Object[] args) {
Expand Down Expand Up @@ -1027,6 +1065,135 @@ public byte[] getPendingFederatorPublicKeyOfType(Object[] args) throws VMExcepti
return publicKey;
}

/**
* Retrieves the proposed federation Bitcoin address as a Base58 string.
*
* <p>
* This method attempts to fetch the address of the proposed federation. If the
* proposed federation is present, it converts the address to its Base58 representation.
* If not, an empty string is returned.
* <p>
*
* @param args Additional arguments (currently unused)
* @return The Base58 encoded Bitcoin address of the proposed federation, or an empty
* string if no proposed federation is present.
*/
public String getProposedFederationAddress(Object[] args) {
logger.trace("getProposedFederationAddress");

return bridgeSupport.getProposedFederationAddress()
.map(Address::toBase58)
.orElse("");
}

/**
* Retrieves the size of the proposed federation, if it exists.
*
* <p>
* This method returns the number of members in the proposed federation. If no proposed federation exists,
* it returns a default response code {@link FederationChangeResponseCode#FEDERATION_NON_EXISTENT} that indicates
* the federation does not exist.
* </p>
*
* @param args unused arguments for this method (can be null or empty).
* @return the size of the proposed federation (number of members), or the default code from
* {@link FederationChangeResponseCode#FEDERATION_NON_EXISTENT} if no proposed federation is available.
*/
public int getProposedFederationSize(Object[] args) {
logger.trace("getProposedFederationSize");

return bridgeSupport.getProposedFederationSize()
.orElse(FederationChangeResponseCode.FEDERATION_NON_EXISTENT.getCode());
}

/**
* Retrieves the creation time of the proposed federation in seconds since the epoch.
*
* <p>
* This method checks if a proposed federation exists and returns its creation time in
* seconds since the Unix epoch. If no proposed federation exists, it returns -1.
* </p>
*
* @param args unused arguments for this method (can be null or empty).
* @return the creation time of the proposed federation in seconds since the epoch,
* or -1 if no proposed federation exists.
*/
public Long getProposedFederationCreationTime(Object[] args) {
logger.trace("getProposedFederationCreationTime");

return bridgeSupport.getProposedFederationCreationTime()
.map(Instant::getEpochSecond)
.orElse(-1L);
}

/**
* Retrieves the block number of the proposed federation's creation.
*
* <p>
* This method checks if a proposed federation exists and returns the block number at which it was created.
* If no proposed federation exists, it returns the default code defined in
* {@link FederationChangeResponseCode#FEDERATION_NON_EXISTENT}.
* </p>
*
* @param args unused arguments for this method (can be null or empty).
* @return the block number of the proposed federation's creation, or
* the code from {@link FederationChangeResponseCode#FEDERATION_NON_EXISTENT}
* if no proposed federation exists.
*/
public long getProposedFederationCreationBlockNumber(Object[] args) {
logger.trace("getProposedFederationCreationBlockNumber");

return bridgeSupport.getProposedFederationCreationBlockNumber()
.orElse((long) FederationChangeResponseCode.FEDERATION_NON_EXISTENT.getCode());
}

/**
* Retrieves the public key of the proposed federator at the specified index and key type.
*
* <p>
* This method extracts the index and key type from the provided arguments, retrieves the
* public key of the proposed federator, and returns it. If no public key is found, an empty byte
* array is returned.
* </p>
*
* <p>
* The first argument in the {@code args} array is expected to be a {@link BigInteger} representing
* the federator's index. The second argument is expected to be a {@link String} representing
* the key type, which is converted into a {@link FederationMember.KeyType}.
* </p>
*
* @param args an array of arguments, where {@code args[0]} is a {@link BigInteger} for the federator's index,
* and {@code args[1]} is a {@link String} for the key type.
* @return a byte array containing the federator's public key, or an empty byte array if not found.
* @throws VMException if an error occurs while processing the key type or if getting an index out of bound exception from method call.
*/
public byte[] getProposedFederatorPublicKeyOfType(Object[] args) throws VMException {
logger.trace("getProposedFederatorPublicKeyOfType");

int index = ((BigInteger) args[0]).intValue();

FederationMember.KeyType keyType;
try {
keyType = FederationMember.KeyType.byValue((String) args[1]);
} catch (Exception e) {
String errorMessage = "[getProposedFederatorPublicKeyOfType] Exception processing public key type";
throw new VMException(errorMessage, e);
}

Optional<byte[]> publicKey;
try {
publicKey = bridgeSupport.getProposedFederatorPublicKeyOfType(index, keyType);
} catch (IndexOutOfBoundsException e) {
String errorMessage = String.format(
"[getProposedFederatorPublicKeyOfType] Exception getting the %s key of member %d", keyType, index
);
throw new VMException(errorMessage, e);
}

return publicKey
.orElse(new byte[]{});
}

public Integer getLockWhitelistSize(Object[] args) {
logger.trace("getLockWhitelistSize");

Expand Down Expand Up @@ -1318,14 +1485,43 @@ public long getEstimatedFeesForNextPegOutEvent(Object[] args) throws IOException

public static BridgeMethods.BridgeMethodExecutor activeAndRetiringFederationOnly(BridgeMethods.BridgeMethodExecutor decoratee, String funcName) {
return (self, args) -> {
boolean isFromActiveFed = BridgeUtils.isFromFederateMember(self.rskTx, self.bridgeSupport.getActiveFederation(), self.signatureCache);

Federation retiringFederation = self.bridgeSupport.getRetiringFederation();
boolean isFromRetiringFed = retiringFederation != null && BridgeUtils.isFromFederateMember(self.rskTx, retiringFederation, self.signatureCache);

if (!isFromActiveFed && !isFromRetiringFed) {
String errorMessage = String.format(
"The sender is not a member of the active or retiring federations and is therefore not authorized to invoke the function: '%s'",
funcName
);
logger.warn(errorMessage);
throw new VMException(errorMessage);
}

return decoratee.execute(self, args);
};
}

public static BridgeMethods.BridgeMethodExecutor activeRetiringAndProposedFederationOnly(BridgeMethods.BridgeMethodExecutor decoratee, String funcName) {
return (self, args) -> {
boolean isFromActiveFed = BridgeUtils.isFromFederateMember(self.rskTx, self.bridgeSupport.getActiveFederation(), self.signatureCache);

Federation retiringFederation = self.bridgeSupport.getRetiringFederation();
boolean isFromRetiringFed = retiringFederation != null && BridgeUtils.isFromFederateMember(self.rskTx, retiringFederation, self.signatureCache);

if (!BridgeUtils.isFromFederateMember(self.rskTx, self.bridgeSupport.getActiveFederation(), self.signatureCache)
&& (retiringFederation == null || !BridgeUtils.isFromFederateMember(self.rskTx, retiringFederation, self.signatureCache))) {
String errorMessage = String.format("Sender is not part of the active or retiring federations, so he is not enabled to call the function '%s'",funcName);
Optional<Federation> proposedFederation = self.bridgeSupport.getProposedFederation();
boolean isFromProposedFed = proposedFederation.isPresent() && BridgeUtils.isFromFederateMember(self.rskTx, proposedFederation.get(), self.signatureCache);

if (!isFromActiveFed && !isFromRetiringFed && !isFromProposedFed) {
String errorMessage = String.format(
"The sender is not a member of the active, retiring, or proposed federations and is therefore not authorized to call the function: '%s'",
funcName
);
logger.warn(errorMessage);
throw new VMException(errorMessage);
}

return decoratee.execute(self, args);
};
}
Expand Down
Loading

0 comments on commit e5982c8

Please sign in to comment.