Search in sources :

Example 76 with PrecompiledTransactionResult

use of org.aion.precompiled.PrecompiledTransactionResult in project aion by aionnetwork.

the class TokenBridgeContractTest method testRingMap.

@Test
public void testRingMap() {
    // override defaults
    this.contract = new TokenBridgeContract(context(OWNER_ADDR, CONTRACT_ADDR), ExternalStateForTests.usingRepository(this.repository), OWNER_ADDR, CONTRACT_ADDR);
    this.connector = this.contract.getConnector();
    ListFVM encodingList = new ListFVM();
    for (ECKey k : members) {
        encodingList.add(new AddressFVM(k.getAddress()));
    }
    byte[] payload = new AbiEncoder(BridgeFuncSig.SIG_RING_INITIALIZE.getSignature(), encodingList).encodeBytes();
    PrecompiledTransactionResult result = this.contract.execute(payload, DEFAULT_NRG);
    assertTrue(result.getStatus().isSuccess());
    // create input byte[]
    byte[] callPayload = new byte[36];
    byte[] encodeBytes = new AbiEncoder(BridgeFuncSig.PURE_RING_MAP.getSignature()).encodeBytes();
    ECKey newKey = ECKeyFac.inst().create();
    byte[] randomAddress = newKey.getAddress();
    System.arraycopy(encodeBytes, 0, callPayload, 0, 4);
    System.arraycopy(randomAddress, 0, callPayload, 4, 32);
    // execute with valid input
    PrecompiledTransactionResult transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    assertTrue(transferResult.getStatus().isSuccess());
    // execute with invalid input
    PrecompiledTransactionResult transferResult2 = this.contract.execute(encodeBytes, DEFAULT_NRG);
    assertEquals("FAILURE", transferResult2.getStatus().causeOfError);
}
Also used : PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) TokenBridgeContract(org.aion.precompiled.contracts.ATB.TokenBridgeContract) AddressFVM(org.aion.zero.impl.precompiled.encoding.AddressFVM) AbiEncoder(org.aion.zero.impl.precompiled.encoding.AbiEncoder) ECKey(org.aion.crypto.ECKey) ListFVM(org.aion.zero.impl.precompiled.encoding.ListFVM) Test(org.junit.Test)

Example 77 with PrecompiledTransactionResult

use of org.aion.precompiled.PrecompiledTransactionResult in project aion by aionnetwork.

the class TokenBridgeContractTest method testRemoveRingMemberNotOwner.

@Test
public void testRemoveRingMemberNotOwner() {
    // override defaults
    this.contract = new TokenBridgeContract(context(OWNER_ADDR, CONTRACT_ADDR), ExternalStateForTests.usingRepository(this.repository), OWNER_ADDR, CONTRACT_ADDR);
    this.connector = this.contract.getConnector();
    ListFVM encodingList = new ListFVM();
    for (ECKey k : members) {
        encodingList.add(new AddressFVM(k.getAddress()));
    }
    // address null - fail
    byte[] payload = new AbiEncoder(BridgeFuncSig.SIG_RING_REMOVE_MEMBER.getSignature()).encodeBytes();
    PrecompiledTransactionResult result = this.contract.execute(payload, DEFAULT_NRG);
    assertEquals("FAILURE", result.getStatus().causeOfError);
    // add new member - fail
    byte[] sig = new AbiEncoder(BridgeFuncSig.SIG_RING_REMOVE_MEMBER.getSignature(), encodingList).encodeBytes();
    // the new member
    byte[] newMember = ECKeyFac.inst().create().getAddress();
    byte[] payload2 = new byte[4 + 32];
    System.arraycopy(sig, 0, payload2, 0, 4);
    System.arraycopy(newMember, 0, payload2, 4, 32);
    PrecompiledTransactionResult result2 = this.contract.execute(payload2, DEFAULT_NRG);
    assertEquals("FAILURE", result2.getStatus().causeOfError);
    // initialize ring
    byte[] ring = new AbiEncoder(BridgeFuncSig.SIG_RING_INITIALIZE.getSignature(), encodingList).encodeBytes();
    this.contract.execute(ring, DEFAULT_NRG);
    // remove member - fail, member does not exist
    byte[] sig3 = new AbiEncoder(BridgeFuncSig.SIG_RING_REMOVE_MEMBER.getSignature(), encodingList).encodeBytes();
    // the new member
    byte[] newMember3 = ECKeyFac.inst().create().getAddress();
    byte[] payload3 = new byte[4 + 32];
    System.arraycopy(sig3, 0, payload3, 0, 4);
    System.arraycopy(newMember3, 0, payload3, 4, 32);
    PrecompiledTransactionResult result3 = this.contract.execute(payload3, DEFAULT_NRG);
    assertEquals("FAILURE", result3.getStatus().causeOfError);
    // override defaults
    this.contract = new TokenBridgeContract(context(AddressUtils.ZERO_ADDRESS, CONTRACT_ADDR), ExternalStateForTests.usingRepository(this.repository), OWNER_ADDR, CONTRACT_ADDR);
    this.connector = this.contract.getConnector();
    // failure, member exists but sender is no longer owner
    byte[] sig4 = new AbiEncoder(BridgeFuncSig.SIG_RING_REMOVE_MEMBER.getSignature(), encodingList).encodeBytes();
    byte[] payload4 = new byte[4 + 32];
    System.arraycopy(sig4, 0, payload4, 0, 4);
    System.arraycopy(members[0].getAddress(), 0, payload4, 4, 32);
    PrecompiledTransactionResult result4 = this.contract.execute(payload4, DEFAULT_NRG);
    assertEquals("FAILURE", result4.getStatus().causeOfError);
}
Also used : PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) TokenBridgeContract(org.aion.precompiled.contracts.ATB.TokenBridgeContract) AddressFVM(org.aion.zero.impl.precompiled.encoding.AddressFVM) AbiEncoder(org.aion.zero.impl.precompiled.encoding.AbiEncoder) ECKey(org.aion.crypto.ECKey) ListFVM(org.aion.zero.impl.precompiled.encoding.ListFVM) Test(org.junit.Test)

Example 78 with PrecompiledTransactionResult

use of org.aion.precompiled.PrecompiledTransactionResult in project aion by aionnetwork.

the class TokenBridgeContractTest method testTransferHugeListLength.

@Test
public void testTransferHugeListLength() {
    BridgeTransfer[] transfers = new BridgeTransfer[10];
    for (int i = 0; i < 10; i++) {
        // generate a unique sourceTransactionHash for each transfer
        byte[] sourceTransactionHash = HashUtil.h256(Integer.toString(i).getBytes());
        transfers[i] = BridgeTransfer.getInstance(BigInteger.ONE, AddressSpecs.computeA0Address(HashUtil.h256(Integer.toHexString(i).getBytes())), sourceTransactionHash);
    }
    // setup
    ReturnDataFromSetup fromSetup = setupForTest(transfers, members);
    PrecompiledTransactionContext submitBundleContext = fromSetup.submitBundleContext;
    byte[] payloadHash = fromSetup.payloadHash;
    byte[] callPayload = fromSetup.callPayload;
    callPayload[50] = (byte) 0x128;
    PrecompiledTransactionResult transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    assertEquals("FAILURE", transferResult.getStatus().causeOfError);
    // VERIFICATION failure
    assertThat(this.contract.execute(ByteUtil.merge(BridgeFuncSig.PURE_ACTION_MAP.getBytes(), payloadHash), 21000L).getReturnData()).isEqualTo(new byte[32]);
    assertEquals("FAILURE", transferResult.getStatus().causeOfError);
    // check that nothing has been changed from the failed transfer
    for (BridgeTransfer b : transfers) {
        assertThat(this.repository.getBalance(new AionAddress(b.getRecipient()))).isEqualTo(BigInteger.ZERO);
    }
    assertThat(this.repository.getBalance(CONTRACT_ADDR)).isEqualTo(BigInteger.valueOf(10));
    assertThat(submitBundleContext.getInternalTransactions()).isEmpty();
    assertThat(submitBundleContext.getLogs()).isEmpty();
}
Also used : PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) AionAddress(org.aion.types.AionAddress) PrecompiledTransactionContext(org.aion.precompiled.type.PrecompiledTransactionContext) BridgeTransfer(org.aion.precompiled.contracts.ATB.BridgeTransfer) Test(org.junit.Test)

Example 79 with PrecompiledTransactionResult

use of org.aion.precompiled.PrecompiledTransactionResult in project aion by aionnetwork.

the class BridgeController method processBundles.

/**
 * Assume bundleHash is not from external source, but rather calculated on our side (on the I/O
 * layer), when {@link BridgeTransfer} list was being created.
 *
 * @param caller, address of the calling account. Used to check whether the address calling is
 *     the relay or not.
 * @param sourceBlockHash, hash of a block on the source blockchain, each block may contain 1 to
 *     N bundles. Used as part of the bundleHash to tie a bundle to a block.
 * @param transfers, {@link BridgeTransfer}
 * @param signatures, a list of signatures from signatories that have signed the bundles.
 * @return {@code ErrCode} indicating whether operation was successful
 * @implNote assume the inputs are properly formatted
 * @implNote will check whether any bundles are {@code 0} value transfers. In such a case, it
 *     indicates that the bridge has faulted, so we should immediately fail all transfers.
 * @implNote {@link BridgeDeserializer} implicitly places a max size for each list to 512.
 */
public ProcessedResults processBundles(@Nonnull final byte[] caller, @Nonnull final byte[] transactionHash, @Nonnull final byte[] sourceBlockHash, @Nonnull final BridgeTransfer[] transfers, @Nonnull final byte[][] signatures) {
    if (!isRingLocked())
        return processError(ErrCode.RING_NOT_LOCKED);
    if (!isRelayer(caller))
        return processError(ErrCode.NOT_RELAYER);
    if (!isWithinSignatureBounds(signatures.length))
        return processError(ErrCode.INVALID_SIGNATURE_BOUNDS);
    /*
         * Computes a unique identifier of the transfer hash for each sourceBlockHash,
         * uniqueness relies on the fact that each
         */
    // verify bundleHash
    byte[] hash = computeBundleHash(sourceBlockHash, transfers);
    // previously successfully broadcast in.
    if (bundleProcessed(hash)) {
        // ATB 6-1, fixed bug: emit stored transactionHash instead of input transaction Hash
        emitSuccessfulTransactionHash(this.connector.getBundle(hash));
        return processSuccess(Collections.emptyList());
    }
    int signed = 0;
    IExternalCapabilitiesForPrecompiled capabilities = CapabilitiesProvider.getExternalCapabilities();
    for (byte[] sigBytes : signatures) {
        if (capabilities.verifyISig(hash, sigBytes) && this.connector.getActiveMember(capabilities.getISigAddress(sigBytes))) {
            signed++;
        }
    }
    int minThresh = this.connector.getMinThresh();
    if (signed < minThresh)
        return processError(ErrCode.NOT_ENOUGH_SIGNATURES);
    // otherwise, we're clear to proceed with transfers
    List<PrecompiledTransactionResult> results = new ArrayList<>();
    for (BridgeTransfer b : transfers) {
        if (b.getTransferValue().compareTo(BigInteger.ZERO) == 0)
            return processError(ErrCode.INVALID_TRANSFER);
        /*
             * Tricky here, we distinguish between two types of failures here:
             *
             * 1) A balance failure indicates we've failed to load the bridge with
             * enough currency to execute, this means the whole transaction should
             * fail and cause the bridge to exit
             *
             * 2) Any other failure indicates that either the contract had code,
             * which means the contract is now considered null.
             *
             * For how this is documented, check the {@code Transferable}
             * interface documentation.
             */
        PrecompiledTransactionResult result;
        if ((result = transferable.transfer(b.getRecipient(), b.getTransferValue())).getStatus().isFailed())
            // no need to return list of transactions, since they're all being dropped
            return processError(ErrCode.INVALID_TRANSFER);
        // otherwise if transfer was successful
        if (result.getStatus().isSuccess())
            if (!emitDistributed(b.getSourceTransactionHash(), b.getRecipient(), b.getTransferValue()))
                return processError(ErrCode.INVALID_TRANSFER);
        results.add(result);
    }
    this.connector.setBundle(hash, transactionHash);
    emitProcessedBundle(sourceBlockHash, hash);
    return processSuccess(results);
}
Also used : IExternalCapabilitiesForPrecompiled(org.aion.precompiled.type.IExternalCapabilitiesForPrecompiled) PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) ArrayList(java.util.ArrayList)

Example 80 with PrecompiledTransactionResult

use of org.aion.precompiled.PrecompiledTransactionResult in project aion by aionnetwork.

the class TokenBridgeContract method transfer.

/**
 * Performs a transfer of value from one account to another, using a method that mimics to the
 * best of it's ability the {@code CALL} opcode. There are some assumptions that become
 * important for any caller to know:
 *
 * @implNote this method will check that the recipient account has no code. This means that we
 *     <b>cannot</b> do a transfer to any contract account.
 * @implNote assumes that the {@code fromValue} derived from the worldState will never be null.
 * @param dest recipient address
 * @param value to be sent (in base units)
 * @return {@code true} if value was performed, {@code false} otherwise
 */
public PrecompiledTransactionResult transfer(@Nonnull final byte[] dest, @Nonnull final BigInteger value) {
    // some initial checks, treat as failure
    if (this.externalState.getBalance(this.contractAddress).compareTo(value) < 0)
        return new PrecompiledTransactionResult(TransactionStatus.nonRevertedFailure("FAILURE"), 0);
    // assemble an internal transaction
    AionAddress sender = this.contractAddress;
    AionAddress destination = new AionAddress(dest);
    BigInteger nonce = this.externalState.getNonce(sender);
    byte[] dataToSend = new byte[0];
    InternalTransaction tx = InternalTransaction.contractCallTransaction(RejectedStatus.NOT_REJECTED, sender, destination, nonce, value, dataToSend, 0L, 1L);
    // add transaction to result
    this.context.addInternalTransaction(tx);
    // increase the nonce and do the transfer without executing code
    this.externalState.incrementNonce(sender);
    this.externalState.addBalance(sender, value.negate());
    this.externalState.addBalance(destination, value);
    // construct result
    return new PrecompiledTransactionResult(TransactionStatus.successful(), 0);
}
Also used : PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) AionAddress(org.aion.types.AionAddress) BigInteger(java.math.BigInteger) InternalTransaction(org.aion.types.InternalTransaction)

Aggregations

PrecompiledTransactionResult (org.aion.precompiled.PrecompiledTransactionResult)114 Test (org.junit.Test)103 PrecompiledTransactionContext (org.aion.precompiled.type.PrecompiledTransactionContext)39 AionAddress (org.aion.types.AionAddress)36 TokenBridgeContract (org.aion.precompiled.contracts.ATB.TokenBridgeContract)26 ECKey (org.aion.crypto.ECKey)25 AbiEncoder (org.aion.precompiled.encoding.AbiEncoder)25 AddressFVM (org.aion.precompiled.encoding.AddressFVM)25 AbiEncoder (org.aion.zero.impl.precompiled.encoding.AbiEncoder)25 AddressFVM (org.aion.zero.impl.precompiled.encoding.AddressFVM)25 BigInteger (java.math.BigInteger)24 ListFVM (org.aion.precompiled.encoding.ListFVM)23 ListFVM (org.aion.zero.impl.precompiled.encoding.ListFVM)23 BridgeTransfer (org.aion.precompiled.contracts.ATB.BridgeTransfer)16 ContractFactory (org.aion.precompiled.ContractFactory)12 Uint128FVM (org.aion.precompiled.encoding.Uint128FVM)11 Uint128FVM (org.aion.zero.impl.precompiled.encoding.Uint128FVM)11 PrecompiledContract (org.aion.precompiled.type.PrecompiledContract)10 InternalTransaction (org.aion.types.InternalTransaction)7 Log (org.aion.types.Log)6