Search in sources :

Example 1 with InternalTransaction

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));
}
Also used : LogInfo(org.ethereum.vm.LogInfo) TypeConverter(org.ethereum.rpc.TypeConverter) HashUtil(org.ethereum.crypto.HashUtil) DslProcessorException(co.rsk.test.dsl.DslProcessorException) CallArguments(org.ethereum.rpc.CallArguments) CallTransaction(org.ethereum.core.CallTransaction) RskAddress(co.rsk.core.RskAddress) TransactionReceipt(org.ethereum.core.TransactionReceipt) Test(org.junit.Test) Coin(co.rsk.core.Coin) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) World(co.rsk.test.World) Block(org.ethereum.core.Block) List(java.util.List) Stream(java.util.stream.Stream) TestSystemProperties(co.rsk.config.TestSystemProperties) ByteUtil(org.ethereum.util.ByteUtil) InternalTransaction(org.ethereum.vm.program.InternalTransaction) GasCost(org.ethereum.vm.GasCost) BigInteger(java.math.BigInteger) EthModuleTestUtils(org.ethereum.util.EthModuleTestUtils) ProgramResult(org.ethereum.vm.program.ProgramResult) Assert(org.junit.Assert) EthModuleTestUtils(org.ethereum.util.EthModuleTestUtils) TransactionReceipt(org.ethereum.core.TransactionReceipt) CallArguments(org.ethereum.rpc.CallArguments) ProgramResult(org.ethereum.vm.program.ProgramResult) World(co.rsk.test.World) InternalTransaction(org.ethereum.vm.program.InternalTransaction) Block(org.ethereum.core.Block) Test(org.junit.Test)

Example 2 with InternalTransaction

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));
}
Also used : LogInfo(org.ethereum.vm.LogInfo) TypeConverter(org.ethereum.rpc.TypeConverter) HashUtil(org.ethereum.crypto.HashUtil) DslProcessorException(co.rsk.test.dsl.DslProcessorException) CallArguments(org.ethereum.rpc.CallArguments) CallTransaction(org.ethereum.core.CallTransaction) RskAddress(co.rsk.core.RskAddress) TransactionReceipt(org.ethereum.core.TransactionReceipt) Test(org.junit.Test) Coin(co.rsk.core.Coin) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) World(co.rsk.test.World) Block(org.ethereum.core.Block) List(java.util.List) Stream(java.util.stream.Stream) TestSystemProperties(co.rsk.config.TestSystemProperties) ByteUtil(org.ethereum.util.ByteUtil) InternalTransaction(org.ethereum.vm.program.InternalTransaction) GasCost(org.ethereum.vm.GasCost) BigInteger(java.math.BigInteger) EthModuleTestUtils(org.ethereum.util.EthModuleTestUtils) ProgramResult(org.ethereum.vm.program.ProgramResult) Assert(org.junit.Assert) EthModuleTestUtils(org.ethereum.util.EthModuleTestUtils) TransactionReceipt(org.ethereum.core.TransactionReceipt) CallArguments(org.ethereum.rpc.CallArguments) ProgramResult(org.ethereum.vm.program.ProgramResult) World(co.rsk.test.World) InternalTransaction(org.ethereum.vm.program.InternalTransaction) Block(org.ethereum.core.Block) Test(org.junit.Test)

Example 3 with InternalTransaction

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();
}
Also used : Coin(co.rsk.bitcoinj.core.Coin) Address(co.rsk.bitcoinj.core.Address) RskAddress(co.rsk.core.RskAddress) Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash) BtcTransaction(co.rsk.bitcoinj.core.BtcTransaction) Keccak256(co.rsk.crypto.Keccak256) InternalTransaction(org.ethereum.vm.program.InternalTransaction) FastBridgeFederationInformation(co.rsk.peg.fastbridge.FastBridgeFederationInformation)

Example 4 with InternalTransaction

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);
}
Also used : RskAddress(co.rsk.core.RskAddress) RskAddress(co.rsk.core.RskAddress) BigInteger(java.math.BigInteger) ECKey(org.ethereum.crypto.ECKey) InternalTransaction(org.ethereum.vm.program.InternalTransaction) ActivationConfig(org.ethereum.config.blockchain.upgrades.ActivationConfig) ActivationConfigsForTest(org.ethereum.config.blockchain.upgrades.ActivationConfigsForTest) Test(org.junit.Test)

Example 5 with InternalTransaction

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);
}
Also used : RskAddress(co.rsk.core.RskAddress) RskAddress(co.rsk.core.RskAddress) BigInteger(java.math.BigInteger) ECKey(org.ethereum.crypto.ECKey) InternalTransaction(org.ethereum.vm.program.InternalTransaction) ActivationConfig(org.ethereum.config.blockchain.upgrades.ActivationConfig) ActivationConfigsForTest(org.ethereum.config.blockchain.upgrades.ActivationConfigsForTest) Test(org.junit.Test)

Aggregations

InternalTransaction (org.ethereum.vm.program.InternalTransaction)15 RskAddress (co.rsk.core.RskAddress)14 Test (org.junit.Test)13 BigInteger (java.math.BigInteger)12 ActivationConfigsForTest (org.ethereum.config.blockchain.upgrades.ActivationConfigsForTest)10 ActivationConfig (org.ethereum.config.blockchain.upgrades.ActivationConfig)9 ECKey (org.ethereum.crypto.ECKey)8 Keccak256 (co.rsk.crypto.Keccak256)7 BtcLockSenderProvider (co.rsk.peg.btcLockSender.BtcLockSenderProvider)6 PeginInstructionsProvider (co.rsk.peg.pegininstructions.PeginInstructionsProvider)6 MutableRepository (org.ethereum.db.MutableRepository)6 Repository (org.ethereum.core.Repository)5 TestSystemProperties (co.rsk.config.TestSystemProperties)3 Coin (co.rsk.core.Coin)3 BtcLockSender (co.rsk.peg.btcLockSender.BtcLockSender)3 World (co.rsk.test.World)3 DslProcessorException (co.rsk.test.dsl.DslProcessorException)3 FileNotFoundException (java.io.FileNotFoundException)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3