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++;
}
}
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++;
}
}
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++;
}
}
Aggregations