Search in sources :

Example 36 with InternalTransaction

use of org.aion.types.InternalTransaction in project aion by aionnetwork.

the class TokenBridgeContractTest method testTransfer.

@Test
public void testTransfer() {
    // override defaults
    PrecompiledTransactionContext initializationContext = context(OWNER_ADDR, CONTRACT_ADDR);
    this.contract = new TokenBridgeContract(initializationContext, ExternalStateForTests.usingRepository(this.repository), OWNER_ADDR, CONTRACT_ADDR);
    this.connector = this.contract.getConnector();
    ListFVM encodingList = new ListFVM();
    for (byte[] k : members) {
        encodingList.add(new AddressFVM(k));
    }
    byte[] payload = new AbiEncoder(BridgeFuncSig.SIG_RING_INITIALIZE.getSignature(), encodingList).encodeBytes();
    PrecompiledTransactionResult result = this.contract.execute(payload, DEFAULT_NRG);
    assertEquals(result.getStatus(), TransactionStatus.successful());
    // set relayer
    byte[] callPayload = new AbiEncoder(BridgeFuncSig.SIG_SET_RELAYER.getSignature(), new AddressFVM(members[0])).encodeBytes();
    PrecompiledTransactionResult transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    assertTrue(transferResult.getStatus().isSuccess());
    // override defaults
    this.repository.addBalance(CONTRACT_ADDR, BigInteger.TEN);
    // we create a new token bridge contract here because we
    // need to change the execution context
    PrecompiledTransactionContext submitBundleContext = context(new AionAddress(members[0]), CONTRACT_ADDR);
    this.contract = new TokenBridgeContract(submitBundleContext, ExternalStateForTests.usingRepository(this.repository), OWNER_ADDR, CONTRACT_ADDR);
    this.connector = this.contract.getConnector();
    // assemble the payload
    byte[] blockHash = capabilities.blake2b("blockHash".getBytes());
    BridgeTransfer[] transfers = new BridgeTransfer[10];
    for (int i = 0; i < 10; i++) {
        // generate a unique sourceTransactionHash for each transfer
        byte[] sourceTransactionHash = capabilities.blake2b(Integer.toString(i).getBytes());
        transfers[i] = BridgeTransfer.getInstance(BigInteger.ONE, capabilities.computeA0Address(capabilities.blake2b(Integer.toHexString(i).getBytes())), sourceTransactionHash);
    }
    byte[] payloadHash = BridgeUtilities.computeBundleHash(blockHash, transfers);
    // ATB-4, do one assert here to check that transactionHash is not set
    assertThat(this.contract.execute(ByteUtil.merge(BridgeFuncSig.PURE_ACTION_MAP.getBytes(), payloadHash), 21000L).getReturnData()).isEqualTo(ByteUtil.EMPTY_WORD);
    byte[][] signatures = new byte[members.length][];
    int i = 0;
    for (byte[] k : members) {
        signatures[i] = capabilities.sign(k, payloadHash);
        i++;
    }
    ListFVM sourceTransactionList = new ListFVM();
    ListFVM addressList = new ListFVM();
    ListFVM uintList = new ListFVM();
    for (BridgeTransfer b : transfers) {
        sourceTransactionList.add(new AddressFVM(b.getSourceTransactionHash()));
        addressList.add(new AddressFVM(b.getRecipient()));
        uintList.add(new Uint128FVM(PrecompiledUtilities.pad(b.getTransferValue().toByteArray(), 16)));
    }
    ListFVM sigChunk1 = new ListFVM();
    ListFVM sigChunk2 = new ListFVM();
    ListFVM sigChunk3 = new ListFVM();
    for (byte[] sig : signatures) {
        sigChunk1.add(new AddressFVM(Arrays.copyOfRange(sig, 0, 32)));
        sigChunk2.add(new AddressFVM(Arrays.copyOfRange(sig, 32, 64)));
        sigChunk3.add(new AddressFVM(Arrays.copyOfRange(sig, 64, 96)));
    }
    callPayload = new AbiEncoder(BridgeFuncSig.SIG_SUBMIT_BUNDLE.getSignature(), new AddressFVM(blockHash), sourceTransactionList, addressList, uintList, sigChunk1, sigChunk2, sigChunk3).encodeBytes();
    transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    // / VERIFICATION
    // ATB-4 assert that transactionHash is now properly set
    // ATB-4, do one assert here to check that transactionHash is not set
    assertThat(this.contract.execute(ByteUtil.merge(BridgeFuncSig.PURE_ACTION_MAP.getBytes(), payloadHash), 21000L).getReturnData()).isEqualTo(submitBundleContext.copyOfTransactionHash());
    assertTrue(transferResult.getStatus().isSuccess());
    for (BridgeTransfer b : transfers) {
        assertThat(this.repository.getBalance(new AionAddress(b.getRecipient()))).isEqualTo(BigInteger.ONE);
    }
    assertThat(this.repository.getBalance(CONTRACT_ADDR)).isEqualTo(BigInteger.ZERO);
    // context verification
    // we expect on successful output:
    // 10 internal transactions (that all succeed)
    // 10 Distributed events
    // 1  ProcessedBundle Event
    assertThat(submitBundleContext.getInternalTransactions().size()).isEqualTo(10);
    i = 0;
    for (InternalTransaction tx : submitBundleContext.getInternalTransactions()) {
        // verify the internal transaction is not rejected
        assertThat(tx.isRejected).isFalse();
        // verify the from is the contract address
        assertThat(tx.sender).isEqualTo(CONTRACT_ADDR);
        // verify that we sent the correct amount
        assertThat(tx.value.intValueExact()).isEqualTo(1);
        // verify that the recipient is what we intended (in the order we submitted)
        assertThat(tx.destination).isEqualTo(new AionAddress(transfers[i].getRecipient()));
        i++;
    }
    // check that proper events are emit
    assertThat(submitBundleContext.getLogs().size()).isEqualTo(11);
    i = 0;
    for (Log l : submitBundleContext.getLogs()) {
        // verify address is correct
        assertThat(l.copyOfAddress()).isEqualTo(CONTRACT_ADDR.toByteArray());
        List<byte[]> topics = l.copyOfTopics();
        // on the 11th log, it should be the processed bundle event
        if (i == 10) {
            assertThat(topics.get(0)).isEqualTo(BridgeEventSig.PROCESSED_BUNDLE.getHashed());
            assertThat(topics.get(1)).isEqualTo(blockHash);
            assertThat(topics.get(2)).isEqualTo(payloadHash);
            continue;
        }
        // otherwise we expect a Distributed event
        assertThat(topics.get(0)).isEqualTo(BridgeEventSig.DISTRIBUTED.getHashed());
        assertThat(topics.get(1)).isEqualTo(transfers[i].getSourceTransactionHash());
        assertThat(topics.get(2)).isEqualTo(transfers[i].getRecipient());
        assertThat(new BigInteger(1, topics.get(3))).isEqualTo(transfers[i].getTransferValue());
        i++;
    }
}
Also used : Uint128FVM(org.aion.precompiled.encoding.Uint128FVM) AionAddress(org.aion.types.AionAddress) Log(org.aion.types.Log) AddressFVM(org.aion.precompiled.encoding.AddressFVM) AbiEncoder(org.aion.precompiled.encoding.AbiEncoder) InternalTransaction(org.aion.types.InternalTransaction) ListFVM(org.aion.precompiled.encoding.ListFVM) PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) PrecompiledTransactionContext(org.aion.precompiled.type.PrecompiledTransactionContext) BigInteger(java.math.BigInteger) Test(org.junit.Test)

Example 37 with InternalTransaction

use of org.aion.types.InternalTransaction in project aion by aionnetwork.

the class TokenBridgeContractTest method testNonA0AddressTransfer.

@Test
public void testNonA0AddressTransfer() {
    // override defaults
    PrecompiledTransactionContext initializationContext = context(OWNER_ADDR, CONTRACT_ADDR);
    this.contract = new TokenBridgeContract(initializationContext, ExternalStateForTests.usingRepository(this.repository), OWNER_ADDR, CONTRACT_ADDR);
    this.connector = this.contract.getConnector();
    ListFVM encodingList = new ListFVM();
    for (byte[] k : members) {
        encodingList.add(new AddressFVM(k));
    }
    byte[] payload = new AbiEncoder(BridgeFuncSig.SIG_RING_INITIALIZE.getSignature(), encodingList).encodeBytes();
    PrecompiledTransactionResult result = this.contract.execute(payload, DEFAULT_NRG);
    assertEquals(result.getStatus(), TransactionStatus.successful());
    // set relayer
    byte[] callPayload = new AbiEncoder(BridgeFuncSig.SIG_SET_RELAYER.getSignature(), new AddressFVM(members[0])).encodeBytes();
    PrecompiledTransactionResult transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    assertTrue(transferResult.getStatus().isSuccess());
    // override defaults
    this.repository.addBalance(CONTRACT_ADDR, BigInteger.TEN);
    // we create a new token bridge contract here because we
    // need to change the execution context
    PrecompiledTransactionContext submitBundleContext = context(new AionAddress(members[0]), CONTRACT_ADDR);
    this.contract = new TokenBridgeContract(submitBundleContext, ExternalStateForTests.usingRepository(this.repository), OWNER_ADDR, CONTRACT_ADDR);
    this.connector = this.contract.getConnector();
    // assemble the payload
    byte[] blockHash = capabilities.blake2b("blockHash".getBytes());
    BridgeTransfer[] transfers = new BridgeTransfer[10];
    for (int i = 0; i < 10; i++) {
        // generate a unique sourceTransactionHash for each transfer
        byte[] sourceTransactionHash = capabilities.blake2b(Integer.toString(i).getBytes());
        transfers[i] = BridgeTransfer.getInstance(BigInteger.ONE, capabilities.blake2b(Integer.toHexString(i).getBytes()), sourceTransactionHash);
    }
    byte[] payloadHash = BridgeUtilities.computeBundleHash(blockHash, transfers);
    // ATB-4, do one assert here to check that transactionHash is not set
    assertThat(this.contract.execute(ByteUtil.merge(BridgeFuncSig.PURE_ACTION_MAP.getBytes(), payloadHash), 21000L).getReturnData()).isEqualTo(ByteUtil.EMPTY_WORD);
    byte[][] signatures = new byte[members.length][];
    int i = 0;
    for (byte[] k : members) {
        signatures[i] = capabilities.sign(k, payloadHash);
        i++;
    }
    ListFVM sourceTransactionList = new ListFVM();
    ListFVM addressList = new ListFVM();
    ListFVM uintList = new ListFVM();
    for (BridgeTransfer b : transfers) {
        sourceTransactionList.add(new AddressFVM(b.getSourceTransactionHash()));
        addressList.add(new AddressFVM(b.getRecipient()));
        uintList.add(new Uint128FVM(PrecompiledUtilities.pad(b.getTransferValue().toByteArray(), 16)));
    }
    ListFVM sigChunk1 = new ListFVM();
    ListFVM sigChunk2 = new ListFVM();
    ListFVM sigChunk3 = new ListFVM();
    for (byte[] sig : signatures) {
        sigChunk1.add(new AddressFVM(Arrays.copyOfRange(sig, 0, 32)));
        sigChunk2.add(new AddressFVM(Arrays.copyOfRange(sig, 32, 64)));
        sigChunk3.add(new AddressFVM(Arrays.copyOfRange(sig, 64, 96)));
    }
    callPayload = new AbiEncoder(BridgeFuncSig.SIG_SUBMIT_BUNDLE.getSignature(), new AddressFVM(blockHash), sourceTransactionList, addressList, uintList, sigChunk1, sigChunk2, sigChunk3).encodeBytes();
    transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    // / VERIFICATION
    // ATB-4 assert that transactionHash is now properly set
    // ATB-4, do one assert here to check that transactionHash is not set
    assertThat(this.contract.execute(ByteUtil.merge(BridgeFuncSig.PURE_ACTION_MAP.getBytes(), payloadHash), 21000L).getReturnData()).isEqualTo(submitBundleContext.copyOfTransactionHash());
    assertTrue(transferResult.getStatus().isSuccess());
    for (BridgeTransfer b : transfers) {
        assertThat(this.repository.getBalance(new AionAddress(b.getRecipient()))).isEqualTo(BigInteger.ONE);
    }
    assertThat(this.repository.getBalance(CONTRACT_ADDR)).isEqualTo(BigInteger.ZERO);
    // context verification
    // we expect on successful output:
    // 10 internal transactions (that all succeed)
    // 10 Distributed events
    // 1  ProcessedBundle Event
    assertThat(submitBundleContext.getInternalTransactions().size()).isEqualTo(10);
    i = 0;
    for (InternalTransaction tx : submitBundleContext.getInternalTransactions()) {
        // verify the internal transaction is not rejected
        assertThat(tx.isRejected).isFalse();
        // verify the from is the contract address
        assertThat(tx.sender).isEqualTo(CONTRACT_ADDR);
        // verify that we sent the correct amount
        assertThat(tx.value.intValueExact()).isEqualTo(1);
        // verify that the recipient is what we intended (in the order we submitted)
        assertThat(tx.destination).isEqualTo(new AionAddress(transfers[i].getRecipient()));
        i++;
    }
    // check that proper events are emit
    assertThat(submitBundleContext.getLogs().size()).isEqualTo(11);
    i = 0;
    for (Log l : submitBundleContext.getLogs()) {
        // verify address is correct
        assertThat(l.copyOfAddress()).isEqualTo(CONTRACT_ADDR.toByteArray());
        List<byte[]> topics = l.copyOfTopics();
        // on the 11th log, it should be the processed bundle event
        if (i == 10) {
            assertThat(topics.get(0)).isEqualTo(BridgeEventSig.PROCESSED_BUNDLE.getHashed());
            assertThat(topics.get(1)).isEqualTo(blockHash);
            assertThat(topics.get(2)).isEqualTo(payloadHash);
            continue;
        }
        // otherwise we expect a Distributed event
        assertThat(topics.get(0)).isEqualTo(BridgeEventSig.DISTRIBUTED.getHashed());
        assertThat(topics.get(1)).isEqualTo(transfers[i].getSourceTransactionHash());
        assertThat(topics.get(2)).isEqualTo(transfers[i].getRecipient());
        assertThat(new BigInteger(1, topics.get(3))).isEqualTo(transfers[i].getTransferValue());
        i++;
    }
}
Also used : Uint128FVM(org.aion.precompiled.encoding.Uint128FVM) AionAddress(org.aion.types.AionAddress) Log(org.aion.types.Log) AddressFVM(org.aion.precompiled.encoding.AddressFVM) AbiEncoder(org.aion.precompiled.encoding.AbiEncoder) InternalTransaction(org.aion.types.InternalTransaction) ListFVM(org.aion.precompiled.encoding.ListFVM) PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) PrecompiledTransactionContext(org.aion.precompiled.type.PrecompiledTransactionContext) BigInteger(java.math.BigInteger) Test(org.junit.Test)

Example 38 with InternalTransaction

use of org.aion.types.InternalTransaction in project aion by aionnetwork.

the class TokenBridgeContractTest method testTransferToSameAddressTwiceInOneBundle.

@Test
public void testTransferToSameAddressTwiceInOneBundle() {
    BridgeTransfer[] transfers = new BridgeTransfer[10];
    // generate a unique sourceTransactionHash for each transfer
    for (int i = 0; i < 10; i++) {
        // send to the same addr more than once
        if (i == 2 || i == 3) {
            byte[] sourceTransactionHashDefault = capabilities.blake2b(Integer.toString(2).getBytes());
            transfers[i] = BridgeTransfer.getInstance(BigInteger.ONE, capabilities.computeA0Address(capabilities.blake2b(Integer.toHexString(2).getBytes())), sourceTransactionHashDefault);
        } else {
            // generate a unique sourceTransactionHash for each transfer
            byte[] sourceTransactionHash = capabilities.blake2b(Integer.toString(i).getBytes());
            transfers[i] = BridgeTransfer.getInstance(BigInteger.ONE, capabilities.computeA0Address(capabilities.blake2b(Integer.toHexString(i).getBytes())), sourceTransactionHash);
        }
    }
    ReturnDataFromSetup fromSetup = setupForTest(transfers, members);
    PrecompiledTransactionContext submitBundleContext = fromSetup.submitBundleContext;
    byte[] blockHash = fromSetup.blockHash;
    byte[] payloadHash = fromSetup.payloadHash;
    byte[] callPayload = fromSetup.callPayload;
    PrecompiledTransactionResult transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    // / VERIFICATION
    assertTrue(transferResult.getStatus().isSuccess());
    int i = 0;
    for (BridgeTransfer b : transfers) {
        if (i == 2 || i == 3) {
            assertThat(this.repository.getBalance(new AionAddress(b.getRecipient()))).isEqualTo(BigInteger.TWO);
        } else {
            assertThat(this.repository.getBalance(new AionAddress(b.getRecipient()))).isEqualTo(BigInteger.ONE);
        }
        i++;
    }
    assertThat(this.repository.getBalance(CONTRACT_ADDR)).isEqualTo(BigInteger.ZERO);
    // context verification
    // we expect on successful output:
    // 10 internal transactions (that all succeed)
    // 10 Distributed events
    // 1  ProcessedBundle Event
    assertThat(submitBundleContext.getInternalTransactions().size()).isEqualTo(10);
    i = 0;
    for (InternalTransaction tx : submitBundleContext.getInternalTransactions()) {
        // verify the internal transaction is not rejected
        assertThat(tx.isRejected).isFalse();
        // verify the from is the contract address
        assertThat(tx.sender).isEqualTo(CONTRACT_ADDR);
        // verify that we sent the correct amount
        assertThat(tx.value.intValueExact()).isEqualTo(1);
        // verify that the recipient is what we intended (in the order we submitted)
        assertThat(tx.destination).isEqualTo(new AionAddress(transfers[i].getRecipient()));
        i++;
    }
    // check that proper events are emit
    assertThat(submitBundleContext.getLogs().size()).isEqualTo(11);
    i = 0;
    for (Log l : submitBundleContext.getLogs()) {
        // verify address is correct
        assertThat(l.copyOfAddress()).isEqualTo(CONTRACT_ADDR.toByteArray());
        List<byte[]> topics = l.copyOfTopics();
        // on the 11th log, it should be the processed bundle event
        if (i == 10) {
            assertThat(topics.get(0)).isEqualTo(BridgeEventSig.PROCESSED_BUNDLE.getHashed());
            assertThat(topics.get(1)).isEqualTo(blockHash);
            assertThat(topics.get(2)).isEqualTo(payloadHash);
            continue;
        }
        // otherwise we expect a Distributed event
        assertThat(topics.get(0)).isEqualTo(BridgeEventSig.DISTRIBUTED.getHashed());
        assertThat(topics.get(1)).isEqualTo(transfers[i].getSourceTransactionHash());
        assertThat(topics.get(2)).isEqualTo(transfers[i].getRecipient());
        assertThat(new BigInteger(1, topics.get(3))).isEqualTo(transfers[i].getTransferValue());
        i++;
    }
}
Also used : PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) AionAddress(org.aion.types.AionAddress) PrecompiledTransactionContext(org.aion.precompiled.type.PrecompiledTransactionContext) Log(org.aion.types.Log) BigInteger(java.math.BigInteger) InternalTransaction(org.aion.types.InternalTransaction) Test(org.junit.Test)

Aggregations

InternalTransaction (org.aion.types.InternalTransaction)38 Test (org.junit.Test)33 AionAddress (org.aion.types.AionAddress)32 AionTransaction (org.aion.base.AionTransaction)20 AionTxExecSummary (org.aion.base.AionTxExecSummary)20 ImportResult (org.aion.zero.impl.core.ImportResult)20 RepositoryCache (org.aion.base.db.RepositoryCache)18 Block (org.aion.zero.impl.types.Block)18 AccountState (org.aion.base.AccountState)17 AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock (org.aion.zero.impl.blockchain.AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock)16 BigInteger (java.math.BigInteger)13 Log (org.aion.types.Log)8 PrecompiledTransactionResult (org.aion.precompiled.PrecompiledTransactionResult)7 PrecompiledTransactionContext (org.aion.precompiled.type.PrecompiledTransactionContext)6 AionTxReceipt (org.aion.base.AionTxReceipt)4 ECKey (org.aion.crypto.ECKey)4 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)4 BlockContext (org.aion.zero.impl.types.BlockContext)4 BridgeTransfer (org.aion.precompiled.contracts.ATB.BridgeTransfer)3 Transaction (org.aion.types.Transaction)3