Search in sources :

Example 1 with IExternalCapabilitiesForPrecompiled

use of org.aion.precompiled.type.IExternalCapabilitiesForPrecompiled in project aion by aionnetwork.

the class TotalCurrencyContract method executeUpdateTotalBalance.

private PrecompiledTransactionResult executeUpdateTotalBalance(byte[] input, long nrg) {
    // update total portion
    if (nrg < COST) {
        return new PrecompiledTransactionResult(TransactionStatus.nonRevertedFailure("OUT_OF_NRG"), 0);
    }
    if (input.length < 114) {
        return new PrecompiledTransactionResult(TransactionStatus.nonRevertedFailure("FAILURE"), 0);
    }
    // process input data
    int offset = 0;
    PrecompiledDataWord chainId = PrecompiledDataWord.fromInt(input[0]);
    offset++;
    byte signum = input[1];
    offset++;
    byte[] amount = new byte[16];
    byte[] sign = new byte[96];
    System.arraycopy(input, offset, amount, 0, 16);
    offset += 16;
    System.arraycopy(input, offset, sign, 0, 96);
    IExternalCapabilitiesForPrecompiled capabilities = CapabilitiesProvider.getExternalCapabilities();
    byte[] payload = new byte[18];
    System.arraycopy(input, 0, payload, 0, 18);
    boolean b = capabilities.verifyEd25519Signature(payload, sign);
    if (!b) {
        return new PrecompiledTransactionResult(TransactionStatus.nonRevertedFailure("FAILURE"), 0);
    }
    // verify public key matches owner
    if (!this.ownerAddress.equals(new AionAddress(capabilities.getEd25519Address(sign)))) {
        return new PrecompiledTransactionResult(TransactionStatus.nonRevertedFailure("FAILURE"), 0);
    }
    // payload processing
    IPrecompiledDataWord totalCurr = this.externalState.getStorageValue(this.address, chainId);
    BigInteger totalCurrBI = totalCurr == null ? BigInteger.ZERO : BIUtil.toBI(totalCurr.copyOfData());
    BigInteger value = BIUtil.toBI(amount);
    if (signum != 0x0 && signum != 0x1) {
        return new PrecompiledTransactionResult(TransactionStatus.nonRevertedFailure("FAILURE"), 0);
    }
    BigInteger finalValue;
    if (signum == 0x0) {
        // addition
        finalValue = totalCurrBI.add(value);
    } else {
        // subtraction
        if (value.compareTo(totalCurrBI) > 0) {
            return new PrecompiledTransactionResult(TransactionStatus.nonRevertedFailure("FAILURE"), 0);
        }
        finalValue = totalCurrBI.subtract(value);
    }
    // store result and successful exit
    this.externalState.addStorageValue(this.address, chainId, PrecompiledDataWord.fromBytes(finalValue.toByteArray()));
    return new PrecompiledTransactionResult(TransactionStatus.successful(), nrg - COST);
}
Also used : IExternalCapabilitiesForPrecompiled(org.aion.precompiled.type.IExternalCapabilitiesForPrecompiled) PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) AionAddress(org.aion.types.AionAddress) IPrecompiledDataWord(org.aion.precompiled.type.IPrecompiledDataWord) BigInteger(java.math.BigInteger) PrecompiledDataWord(org.aion.precompiled.type.PrecompiledDataWord) IPrecompiledDataWord(org.aion.precompiled.type.IPrecompiledDataWord)

Example 2 with IExternalCapabilitiesForPrecompiled

use of org.aion.precompiled.type.IExternalCapabilitiesForPrecompiled 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)

Aggregations

PrecompiledTransactionResult (org.aion.precompiled.PrecompiledTransactionResult)2 IExternalCapabilitiesForPrecompiled (org.aion.precompiled.type.IExternalCapabilitiesForPrecompiled)2 BigInteger (java.math.BigInteger)1 ArrayList (java.util.ArrayList)1 IPrecompiledDataWord (org.aion.precompiled.type.IPrecompiledDataWord)1 PrecompiledDataWord (org.aion.precompiled.type.PrecompiledDataWord)1 AionAddress (org.aion.types.AionAddress)1