Skip to content

Commit

Permalink
Merge pull request #2267 from rsksmart/arrowhead-master-merge
Browse files Browse the repository at this point in the history
Merge ARROWHEAD-6.0.0 into master
  • Loading branch information
Vovchyk authored Mar 6, 2024
2 parents 64faf03 + 00b57ea commit b1e65d3
Show file tree
Hide file tree
Showing 44 changed files with 4,316 additions and 1,226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public class BridgeMainNetConstants extends BridgeConstants {

numberOfBlocksBetweenPegouts = 360; // 3 hours of RSK blocks (considering 1 block every 30 seconds)

btcHeightWhenPegoutTxIndexActivates = 100; // TODO: TBD and change current mock value. This is an estimation of the btc block number once RSKIP379 is activated.
btcHeightWhenPegoutTxIndexActivates = 837_589; // Estimated date Wed, 03 Apr 2024 15:00:00 GMT. 832,430 was the block number at time of calculation
pegoutTxIndexGracePeriodInBtcBlocks = 4_320; // 30 days in BTC blocks (considering 1 block every 10 minutes)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ public class BridgeTestNetConstants extends BridgeConstants {

numberOfBlocksBetweenPegouts = 360; // 3 hours of RSK blocks (considering 1 block every 30 seconds)

btcHeightWhenPegoutTxIndexActivates = 150; // TODO: TBD and change current mock value. This is an estimation of the btc block number once RSKIP379 is activated.
pegoutTxIndexGracePeriodInBtcBlocks = 4_320; // 30 days in BTC blocks (considering 1 block every 10 minutes)
btcHeightWhenPegoutTxIndexActivates = 2_589_553; // Estimated date Wed, 20 Mar 2024 15:00:00 GMT. 2,579,823 was the block number at time of calculation
pegoutTxIndexGracePeriodInBtcBlocks = 1_440; // 10 days in BTC blocks (considering 1 block every 10 minutes)
}

public static BridgeTestNetConstants getInstance() {
Expand Down
173 changes: 128 additions & 45 deletions rskj-core/src/main/java/co/rsk/peg/Bridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
*/
package co.rsk.peg;

import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP417;

import co.rsk.bitcoinj.core.*;
import co.rsk.bitcoinj.script.Script;
import co.rsk.bitcoinj.store.BlockStoreException;
import co.rsk.config.BridgeConstants;
import co.rsk.core.RskAddress;
import co.rsk.crypto.Keccak256;
import co.rsk.panic.PanicProcessor;
import co.rsk.peg.BridgeMethods.BridgeMethodExecutor;
import co.rsk.peg.bitcoin.MerkleBranch;
import co.rsk.peg.federation.Federation;
import co.rsk.peg.federation.FederationMember;
Expand All @@ -39,6 +42,7 @@
import org.ethereum.core.*;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.DataWord;
import org.ethereum.vm.MessageCall.MsgType;
import org.ethereum.vm.PrecompiledContractArgs;
import org.ethereum.vm.PrecompiledContracts;
import org.ethereum.vm.exception.VMException;
Expand Down Expand Up @@ -225,15 +229,34 @@ public class Bridge extends PrecompiledContracts.PrecompiledContract {
private final BiFunction<List<Sha256Hash>, Integer, MerkleBranch> merkleBranchFactory;

private final SignatureCache signatureCache;

public Bridge(RskAddress contractAddress, Constants constants, ActivationConfig activationConfig,
BridgeSupportFactory bridgeSupportFactory, SignatureCache signatureCache) {
this(contractAddress, constants, activationConfig, bridgeSupportFactory, MerkleBranch::new, signatureCache);
private MsgType msgType;

public Bridge(
RskAddress contractAddress,
Constants constants,
ActivationConfig activationConfig,
BridgeSupportFactory bridgeSupportFactory,
SignatureCache signatureCache) {

this(
contractAddress,
constants,
activationConfig,
bridgeSupportFactory,
MerkleBranch::new,
signatureCache
);
}

@VisibleForTesting
Bridge(RskAddress contractAddress, Constants constants, ActivationConfig activationConfig,
BridgeSupportFactory bridgeSupportFactory, BiFunction<List<Sha256Hash>, Integer, MerkleBranch> merkleBranchFactory, SignatureCache signatureCache) {
Bridge(
RskAddress contractAddress,
Constants constants,
ActivationConfig activationConfig,
BridgeSupportFactory bridgeSupportFactory,
BiFunction<List<Sha256Hash>, Integer, MerkleBranch> merkleBranchFactory,
SignatureCache signatureCache) {

this.bridgeSupportFactory = bridgeSupportFactory;
this.contractAddress = contractAddress;
this.constants = constants;
Expand Down Expand Up @@ -318,12 +341,14 @@ public void init(PrecompiledContractArgs args) {
Block rskExecutionBlock = args.getExecutionBlock();
this.activations = activationConfig.forBlock(rskExecutionBlock.getNumber());
this.rskTx = args.getTransaction();
this.msgType = args.getMsgType();

this.bridgeSupport = bridgeSupportFactory.newInstance(
args.getRepository(),
rskExecutionBlock,
contractAddress,
args.getLogs());
args.getRepository(),
rskExecutionBlock,
contractAddress,
args.getLogs()
);
}

@Override
Expand All @@ -344,50 +369,98 @@ public byte[] execute(byte[] data) throws VMException {
// Function parsing from data returned null => invalid function selected, halt!
if (bridgeParsedData == null) {
String errorMessage = String.format("Invalid data given: %s.", ByteUtil.toHexString(data));
logger.info(errorMessage);
if (activations.isActive(ConsensusRule.RSKIP88)) {
throw new BridgeIllegalArgumentException(errorMessage);
logger.info("[execute] {}", errorMessage);
if (!activations.isActive(ConsensusRule.RSKIP88)) {
return null;
}

return null;
}

// If this is not a local call, then first check whether the function
// allows for non-local calls
if (activations.isActive(ConsensusRule.RSKIP88) &&
!isLocalCall() &&
bridgeParsedData.bridgeMethod.onlyAllowsLocalCalls(this, bridgeParsedData.args)) {

String errorMessage = String.format("Non-local-call to %s. Returning without execution.", bridgeParsedData.bridgeMethod.getFunction().name);
logger.info(errorMessage);
throw new BridgeIllegalArgumentException(errorMessage);
}

validateCall(bridgeParsedData);
Optional<?> result;
try {
// bridgeParsedData.function should be one of the CallTransaction.Function declared above.
// If the user tries to call an non-existent function, parseData() will return null.
result = bridgeParsedData.bridgeMethod.getExecutor().execute(this, bridgeParsedData.args);
result = executeBridgeMethod(bridgeParsedData);
} catch (BridgeIllegalArgumentException ex) {
String errorMessage = String.format("Error executing: %s", bridgeParsedData.bridgeMethod);
logger.warn(errorMessage, ex);
if (activations.isActive(ConsensusRule.RSKIP88)) {
throw new BridgeIllegalArgumentException(errorMessage);
if (shouldReturnNullInsteadOfException()) {
return null;
}

return null;
throw ex;
}

teardown();

return result.map(bridgeParsedData.bridgeMethod.getFunction()::encodeOutputs).orElse(null);
byte[] voidReturnValue = calculateVoidReturnValue();
return result.map(bridgeParsedData.bridgeMethod.getFunction()::encodeOutputs).orElse(voidReturnValue);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
panicProcessor.panic("bridgeexecute", ex.getMessage());
throw new VMException(String.format("Exception executing bridge: %s", ex.getMessage()), ex);
}
}

private void validateCall(BridgeParsedData bridgeParsedData) throws BridgeIllegalArgumentException {
validateLocalCall(bridgeParsedData);
validateCallMessageType(bridgeParsedData);
}

private void validateLocalCall(BridgeParsedData bridgeParsedData) throws BridgeIllegalArgumentException {
// If this is not a local call, then check whether the function allows for non-local calls
if (activations.isActive(ConsensusRule.RSKIP88) &&
!isLocalCall() &&
bridgeParsedData.bridgeMethod.onlyAllowsLocalCalls(this, bridgeParsedData.args)) {

String errorMessage = String.format(
"Non-local-call to %s. Returning without execution.",
bridgeParsedData.bridgeMethod.getFunction().name
);
logger.info("[validateLocalCall] {}", errorMessage);
throw new BridgeIllegalArgumentException(errorMessage);
}
}

private void validateCallMessageType(BridgeParsedData bridgeParsedData) throws BridgeIllegalArgumentException {
if (activations.isActive(RSKIP417) &&
!bridgeParsedData.bridgeMethod.acceptsThisTypeOfCall(this.msgType)) {
String errorMessage = String.format(
"Call type (%s) not accepted by %s. Returning without execution.",
this.msgType.name(),
bridgeParsedData.bridgeMethod.getFunction().name
);
logger.info("[validateCallMessageType] {}", errorMessage);

throw new BridgeIllegalArgumentException(errorMessage);
}
}

private Optional<?> executeBridgeMethod(BridgeParsedData bridgeParsedData) throws Exception {
try {
// bridgeParsedData.function should be one of the CallTransaction.Function declared above.
// If the user tries to call an non-existent function, parseData() will return null.
BridgeMethodExecutor executor = bridgeParsedData.bridgeMethod.getExecutor();
return executor.execute(this, bridgeParsedData.args);
} catch (BridgeIllegalArgumentException ex) {
String errorMessage = String.format("Error executing: %s", bridgeParsedData.bridgeMethod);
logger.warn(errorMessage, ex);

throw new BridgeIllegalArgumentException(errorMessage);
}
}

private boolean shouldReturnNullInsteadOfException() {
return !activations.isActive(ConsensusRule.RSKIP88);
}

private byte[] calculateVoidReturnValue() {
if (shouldReturnNullOnVoidMethods()) {
return null;
}
return new byte[]{};
}

private boolean shouldReturnNullOnVoidMethods() {
return !activations.isActive(RSKIP417);
}

private void teardown() throws IOException {
bridgeSupport.save();
}
Expand Down Expand Up @@ -630,7 +703,7 @@ public byte[] getBtcBlockchainBlockHashAtDepth(Object[] args) throws VMException
logger.trace("getBtcBlockchainBlockHashAtDepth");

int depth = ((BigInteger) args[0]).intValue();
Sha256Hash blockHash = null;
Sha256Hash blockHash;
try {
blockHash = bridgeSupport.getBtcBlockchainBlockHashAtDepth(depth);
} catch (Exception e) {
Expand Down Expand Up @@ -833,8 +906,8 @@ public Integer createFederation(Object[] args) throws BridgeIllegalArgumentExcep
logger.trace("createFederation");

return bridgeSupport.voteFederationChange(
rskTx,
new ABICallSpec("create", new byte[][]{})
rskTx,
new ABICallSpec("create", new byte[][]{})
);
}

Expand All @@ -850,8 +923,8 @@ public Integer addFederatorPublicKey(Object[] args) throws BridgeIllegalArgument
}

return bridgeSupport.voteFederationChange(
rskTx,
new ABICallSpec("add", new byte[][]{ publicKeyBytes })
rskTx,
new ABICallSpec("add", new byte[][]{ publicKeyBytes })
);
}

Expand All @@ -863,8 +936,11 @@ public Integer addFederatorPublicKeyMultikey(Object[] args) throws BridgeIllegal
byte[] mstPublicKeyBytes = (byte[]) args[2];

return bridgeSupport.voteFederationChange(
rskTx,
new ABICallSpec("add-multi", new byte[][]{ btcPublicKeyBytes, rskPublicKeyBytes, mstPublicKeyBytes })
rskTx,
new ABICallSpec(
"add-multi",
new byte[][]{ btcPublicKeyBytes, rskPublicKeyBytes, mstPublicKeyBytes }
)
);
}

Expand All @@ -880,8 +956,8 @@ public Integer commitFederation(Object[] args) throws BridgeIllegalArgumentExcep
}

return bridgeSupport.voteFederationChange(
rskTx,
new ABICallSpec("commit", new byte[][]{ hash })
rskTx,
new ABICallSpec("commit", new byte[][]{ hash })
);
}

Expand Down Expand Up @@ -1102,7 +1178,14 @@ public void registerBtcCoinbaseTransaction(Object[] args) throws VMException {
byte[] pmtSerialized = (byte[]) args[2];
Sha256Hash witnessMerkleRoot = Sha256Hash.wrap((byte[]) args[3]);
byte[] witnessReservedValue = (byte[]) args[4];
bridgeSupport.registerBtcCoinbaseTransaction(btcTxSerialized, blockHash, pmtSerialized, witnessMerkleRoot, witnessReservedValue);

bridgeSupport.registerBtcCoinbaseTransaction(
btcTxSerialized,
blockHash,
pmtSerialized,
witnessMerkleRoot,
witnessReservedValue
);
}

public boolean hasBtcBlockCoinbaseTransactionInformation(Object[] args) {
Expand Down
Loading

0 comments on commit b1e65d3

Please sign in to comment.