use of org.ethereum.vm.program.InternalTransaction in project rskj by rsksmart.
the class EthModuleGasEstimationDSLTest method estimateGas_nestedCallsWithValueGasRetainAndStorageRefund.
/**
* Send 1 rBTC accross three contracts, then the last contract frees a storage cell and does a CALL with value
* NOTE: each nested call retains 10000 gas to emit events
*/
@Test
public void estimateGas_nestedCallsWithValueGasRetainAndStorageRefund() throws FileNotFoundException, DslProcessorException {
World world = World.processedWorld("dsl/eth_module/estimateGas/nestedCallsWithValueAndStorageRefund.txt");
TransactionReceipt contractDeployA = world.getTransactionReceiptByName("tx01");
String contractAddressA = "0x" + contractDeployA.getTransaction().getContractAddress().toHexString();
byte[] status = contractDeployA.getStatus();
assertNotNull(status);
assertEquals(1, status.length);
assertEquals(0x01, status[0]);
assertEquals("0x6252703f5ba322ec64d3ac45e56241b7d9e481ad", contractAddressA);
TransactionReceipt contractDeployB = world.getTransactionReceiptByName("tx02");
String contractAddressB = "0x" + contractDeployB.getTransaction().getContractAddress().toHexString();
byte[] status2 = contractDeployB.getStatus();
assertNotNull(status2);
assertEquals(1, status2.length);
assertEquals(0x01, status2[0]);
assertEquals("0x56aa252dd82173789984fa164ee26ce2da9336ff", contractAddressB);
TransactionReceipt contractDeployC = world.getTransactionReceiptByName("tx03");
String contractAddressC = "0x" + contractDeployC.getTransaction().getContractAddress().toHexString();
byte[] status3 = contractDeployC.getStatus();
assertNotNull(status3);
assertEquals(1, status3.length);
assertEquals(0x01, status3[0]);
assertEquals("0x27444fbce96cb2d27b94e116d1506d7739c05862", contractAddressC);
EthModuleTestUtils.EthModuleGasEstimation eth = EthModuleTestUtils.buildBasicEthModuleForGasEstimation(world);
Block block = world.getBlockChain().getBestBlock();
// call callAddressWithValue, it should start the nested calls
final CallArguments args = new CallArguments();
args.setTo(contractAddressA);
args.setValue(TypeConverter.toQuantityJsonHex(1));
args.setNonce(TypeConverter.toQuantityJsonHex(6));
args.setGas(TypeConverter.toQuantityJsonHex(BLOCK_GAS_LIMIT));
// callAddressWithValue()
args.setData("0xfb60f709");
ProgramResult callConstant = eth.callConstant(args, block);
List<InternalTransaction> internalTransactions = callConstant.getInternalTransactions();
assertTrue(internalTransactions.stream().allMatch(i -> i.getValue().equals(Coin.valueOf(1))));
assertEquals(3, internalTransactions.size());
assertEquals(3, callConstant.getLogInfoList().size());
assertEvents(callConstant, "NestedCallWV", 2);
assertEvents(callConstant, "LastCall", 1);
assertTrue(callConstant.getMovedRemainingGasToChild());
long callConstantGasUsed = callConstant.getGasUsed();
long estimatedGas = estimateGas(eth, args);
assertTrue(eth.getEstimationResult().getDeductedRefund() > 0);
assertTrue(callConstant.getDeductedRefund() > 0);
assertEquals(callConstant.getGasUsedBeforeRefunds() / 2, callConstant.getDeductedRefund());
assertEquals(callConstantGasUsed + callConstant.getDeductedRefund(), estimatedGas);
args.setGas(TypeConverter.toQuantityJsonHex(callConstantGasUsed));
assertFalse(runWithArgumentsAndBlock(eth, args, block));
args.setGas(TypeConverter.toQuantityJsonHex(estimatedGas));
assertTrue(runWithArgumentsAndBlock(eth, args, block));
args.setGas(TypeConverter.toQuantityJsonHex(estimatedGas - 1));
assertFalse(runWithArgumentsAndBlock(eth, args, block));
}
use of org.ethereum.vm.program.InternalTransaction in project rskj by rsksmart.
the class EthModuleGasEstimationDSLTest method estimateGas_nestedCallsWithValueAndGasRetain.
/**
* Sending one rBTC across three contracts, they will perfomrm 3 CALLs with value.
* NOTE: each nested call retains 10000 gas to emit events
*/
@Test
public void estimateGas_nestedCallsWithValueAndGasRetain() throws FileNotFoundException, DslProcessorException {
World world = World.processedWorld("dsl/eth_module/estimateGas/nestedCallsWithValue.txt");
TransactionReceipt contractDeployA = world.getTransactionReceiptByName("tx01");
String contractAddressA = "0x" + contractDeployA.getTransaction().getContractAddress().toHexString();
byte[] status = contractDeployA.getStatus();
assertNotNull(status);
assertEquals(1, status.length);
assertEquals(0x01, status[0]);
assertEquals("0x6252703f5ba322ec64d3ac45e56241b7d9e481ad", contractAddressA);
TransactionReceipt contractDeployB = world.getTransactionReceiptByName("tx02");
String contractAddressB = "0x" + contractDeployB.getTransaction().getContractAddress().toHexString();
byte[] status2 = contractDeployB.getStatus();
assertNotNull(status2);
assertEquals(1, status2.length);
assertEquals(0x01, status2[0]);
assertEquals("0x56aa252dd82173789984fa164ee26ce2da9336ff", contractAddressB);
TransactionReceipt contractDeployC = world.getTransactionReceiptByName("tx03");
String contractAddressC = "0x" + contractDeployC.getTransaction().getContractAddress().toHexString();
byte[] status3 = contractDeployC.getStatus();
assertNotNull(status3);
assertEquals(1, status3.length);
assertEquals(0x01, status3[0]);
assertEquals("0x27444fbce96cb2d27b94e116d1506d7739c05862", contractAddressC);
EthModuleTestUtils.EthModuleGasEstimation eth = EthModuleTestUtils.buildBasicEthModuleForGasEstimation(world);
Block block = world.getBlockChain().getBestBlock();
// call callAddressWithValue, it should start the nested calls
final CallArguments args = new CallArguments();
args.setTo(contractAddressA);
args.setValue(TypeConverter.toQuantityJsonHex(1));
args.setNonce(TypeConverter.toQuantityJsonHex(6));
args.setGas(TypeConverter.toQuantityJsonHex(BLOCK_GAS_LIMIT));
// callAddressWithValue()
args.setData("0xfb60f709");
ProgramResult callConstant = eth.callConstant(args, block);
List<InternalTransaction> internalTransactions = callConstant.getInternalTransactions();
assertTrue(internalTransactions.stream().allMatch(i -> i.getValue().equals(Coin.valueOf(1))));
assertEquals(2, internalTransactions.size());
assertEquals(3, callConstant.getLogInfoList().size());
assertEvents(callConstant, "NestedCallWV", 2);
assertEvents(callConstant, "LastCall", 1);
assertTrue(callConstant.getMovedRemainingGasToChild());
long callConstantGasUsed = callConstant.getGasUsed();
long estimatedGas = estimateGas(eth, args);
assertEquals(0, eth.getEstimationResult().getDeductedRefund());
assertEquals(callConstant.getGasUsed(), estimatedGas);
args.setGas(TypeConverter.toQuantityJsonHex(callConstantGasUsed));
assertTrue(runWithArgumentsAndBlock(eth, args, block));
assertEquals(callConstantGasUsed, estimatedGas);
args.setGas(TypeConverter.toQuantityJsonHex(estimatedGas));
assertTrue(runWithArgumentsAndBlock(eth, args, block));
args.setGas(TypeConverter.toQuantityJsonHex(estimatedGas - 1));
assertFalse(runWithArgumentsAndBlock(eth, args, block));
}
use of org.ethereum.vm.program.InternalTransaction in project rskj by rsksmart.
the class BridgeSupport method registerFastBridgeBtcTransaction.
public BigInteger registerFastBridgeBtcTransaction(Transaction rskTx, byte[] btcTxSerialized, int height, byte[] pmtSerialized, Keccak256 derivationArgumentsHash, Address userRefundAddress, RskAddress lbcAddress, Address lpBtcAddress, boolean shouldTransferToContract) throws BlockStoreException, IOException, BridgeIllegalArgumentException {
if (!BridgeUtils.isContractTx(rskTx)) {
logger.debug("[registerFastBridgeBtcTransaction] (rskTx:{}) Sender not a contract", rskTx.getHash());
return BigInteger.valueOf(FAST_BRIDGE_UNPROCESSABLE_TX_NOT_CONTRACT_ERROR_CODE);
}
if (!rskTx.getSender().equals(lbcAddress)) {
logger.debug("[registerFastBridgeBtcTransaction] Expected sender to be the same as lbcAddress. (sender: {}) (lbcAddress:{})", rskTx.getSender(), lbcAddress);
return BigInteger.valueOf(FAST_BRIDGE_UNPROCESSABLE_TX_INVALID_SENDER_ERROR_CODE);
}
Context.propagate(btcContext);
Sha256Hash btcTxHash = BtcTransactionFormatUtils.calculateBtcTxHash(btcTxSerialized);
Keccak256 fastBridgeDerivationHash = getFastBridgeDerivationHash(derivationArgumentsHash, userRefundAddress, lpBtcAddress, lbcAddress);
if (provider.isFastBridgeFederationDerivationHashUsed(btcTxHash, fastBridgeDerivationHash)) {
logger.debug("[registerFastBridgeBtcTransaction] Transaction and derivation hash already used");
return BigInteger.valueOf(FAST_BRIDGE_UNPROCESSABLE_TX_ALREADY_PROCESSED_ERROR_CODE);
}
if (!validationsForRegisterBtcTransaction(btcTxHash, height, pmtSerialized, btcTxSerialized)) {
logger.debug("[registerFastBridgeBtcTransaction] (btcTx:{}) error during validationsForRegisterBtcTransaction", btcTxHash);
return BigInteger.valueOf(FAST_BRIDGE_UNPROCESSABLE_TX_VALIDATIONS_ERROR);
}
BtcTransaction btcTx = new BtcTransaction(bridgeConstants.getBtcParams(), btcTxSerialized);
btcTx.verify();
Sha256Hash btcTxHashWithoutWitness = btcTx.getHash(false);
if (!btcTxHashWithoutWitness.equals(btcTxHash) && provider.isFastBridgeFederationDerivationHashUsed(btcTxHashWithoutWitness, derivationArgumentsHash)) {
logger.debug("[registerFastBridgeBtcTransaction] Transaction and derivation hash already used");
return BigInteger.valueOf(FAST_BRIDGE_UNPROCESSABLE_TX_ALREADY_PROCESSED_ERROR_CODE);
}
FastBridgeFederationInformation fastBridgeFederationInformation = createFastBridgeFederationInformation(fastBridgeDerivationHash);
Address fastBridgeFedAddress = fastBridgeFederationInformation.getFastBridgeFederationAddress(bridgeConstants.getBtcParams());
Coin totalAmount = getAmountSentToAddress(btcTx, fastBridgeFedAddress);
if (totalAmount == Coin.ZERO) {
logger.debug("[registerFastBridgeBtcTransaction] Amount sent can't be 0");
return BigInteger.valueOf(FAST_BRIDGE_UNPROCESSABLE_TX_VALUE_ZERO_ERROR);
}
if (!verifyLockDoesNotSurpassLockingCap(btcTx, totalAmount)) {
InternalTransaction internalTx = (InternalTransaction) rskTx;
logger.info("[registerFastBridgeBtcTransaction] Locking cap surpassed, going to return funds!");
WalletProvider walletProvider = createFastBridgeWalletProvider(fastBridgeFederationInformation);
provider.markFastBridgeFederationDerivationHashAsUsed(btcTxHash, fastBridgeDerivationHash);
if (shouldTransferToContract) {
logger.debug("[registerFastBridgeBtcTransaction] Returning to liquidity provider");
generateRejectionRelease(btcTx, lpBtcAddress, fastBridgeFedAddress, new Keccak256(internalTx.getOriginHash()), totalAmount, walletProvider);
return BigInteger.valueOf(FAST_BRIDGE_REFUNDED_LP_ERROR_CODE);
} else {
logger.debug("[registerFastBridgeBtcTransaction] Returning to user");
generateRejectionRelease(btcTx, userRefundAddress, fastBridgeFedAddress, new Keccak256(internalTx.getOriginHash()), totalAmount, walletProvider);
return BigInteger.valueOf(FAST_BRIDGE_REFUNDED_USER_ERROR_CODE);
}
}
transferTo(lbcAddress, co.rsk.core.Coin.fromBitcoin(totalAmount));
saveFastBridgeDataInStorage(btcTxHashWithoutWitness, fastBridgeDerivationHash, fastBridgeFederationInformation, getUTXOsForAddress(btcTx, fastBridgeFedAddress));
logger.info("[registerFastBridgeBtcTransaction] (btcTx:{}) transaction registered successfully", btcTxHashWithoutWitness);
return co.rsk.core.Coin.fromBitcoin(totalAmount).asBigInteger();
}
use of org.ethereum.vm.program.InternalTransaction in project rskj by rsksmart.
the class BridgeSupportTest method registerFastBridgeBtcTransaction_TxAlreadySavedInStorage_returnsError.
@Test
public void registerFastBridgeBtcTransaction_TxAlreadySavedInStorage_returnsError() throws IOException, BlockStoreException, BridgeIllegalArgumentException {
ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class);
when(activations.isActive(ConsensusRule.RSKIP176)).thenReturn(true);
BridgeStorageProvider provider = mock(BridgeStorageProvider.class);
when(provider.isFastBridgeFederationDerivationHashUsed(any(), any())).thenReturn(true);
BtcTransaction tx = new BtcTransaction(bridgeConstants.getBtcParams());
ECKey key = ECKey.fromPublicOnly(new BtcECKey().getPubKey());
RskAddress lbcAddress = new RskAddress(key.getAddress());
BridgeSupport bridgeSupport = spy(getBridgeSupport(bridgeConstants, provider, mock(Repository.class), mock(BridgeEventLogger.class), null, mock(BtcBlockStoreWithCache.Factory.class), activations));
doReturn(PegTestUtils.createHash3(5)).when(bridgeSupport).getFastBridgeDerivationHash(any(), any(), any(), any());
InternalTransaction rskTx = new InternalTransaction(Keccak256.ZERO_HASH.getBytes(), 0, 0, null, null, null, lbcAddress.getBytes(), null, null, null, null);
BigInteger result = bridgeSupport.registerFastBridgeBtcTransaction(rskTx, tx.bitcoinSerialize(), 100, Hex.decode("ab"), PegTestUtils.createHash3(0), mock(Address.class), lbcAddress, mock(Address.class), false);
Assert.assertEquals(BigInteger.valueOf(BridgeSupport.FAST_BRIDGE_UNPROCESSABLE_TX_ALREADY_PROCESSED_ERROR_CODE), result);
}
use of org.ethereum.vm.program.InternalTransaction in project rskj by rsksmart.
the class BridgeSupportTest method registerFastBridgeBtcTransaction_validationsForRegisterBtcTransaction_returns_false.
@Test
public void registerFastBridgeBtcTransaction_validationsForRegisterBtcTransaction_returns_false() throws IOException, BlockStoreException, BridgeIllegalArgumentException {
ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class);
when(activations.isActive(ConsensusRule.RSKIP176)).thenReturn(true);
BridgeStorageProvider provider = mock(BridgeStorageProvider.class);
BtcTransaction tx = new BtcTransaction(bridgeConstants.getBtcParams());
ECKey key = ECKey.fromPublicOnly(new BtcECKey().getPubKey());
RskAddress lbcAddress = new RskAddress(key.getAddress());
BridgeSupport bridgeSupport = spy(getBridgeSupport(bridgeConstants, provider, mock(Repository.class), mock(BridgeEventLogger.class), null, mock(BtcBlockStoreWithCache.Factory.class), activations));
doReturn(PegTestUtils.createHash3(5)).when(bridgeSupport).getFastBridgeDerivationHash(any(), any(), any(), any());
InternalTransaction rskTx = new InternalTransaction(Keccak256.ZERO_HASH.getBytes(), 0, 0, null, null, null, lbcAddress.getBytes(), null, null, null, null);
BigInteger result = bridgeSupport.registerFastBridgeBtcTransaction(rskTx, tx.bitcoinSerialize(), 100, Hex.decode("ab"), PegTestUtils.createHash3(0), mock(Address.class), lbcAddress, mock(Address.class), false);
Assert.assertEquals(BigInteger.valueOf(BridgeSupport.FAST_BRIDGE_UNPROCESSABLE_TX_VALIDATIONS_ERROR), result);
}
Aggregations