Search in sources :

Example 81 with AionAddress

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

the class AionBlockchainImpl method createNewStakingBlock.

private StakingBlock createNewStakingBlock(Block parent, List<AionTransaction> txs, byte[] newSeed, byte[] signingPublicKey, byte[] coinbase) {
    BlockHeader parentHdr = parent.getHeader();
    byte[] sealedSeed = newSeed;
    if (!forkUtility.isUnityForkActive(parentHdr.getNumber() + 1)) {
        LOG.debug("Unity fork has not been enabled! Can't create the staking blocks");
        return null;
    }
    byte[] parentSeed;
    BigInteger newDiff;
    if (parentHdr.getSealType() == Seal.PROOF_OF_STAKE) {
        LOG.warn("Tried to create 2 PoS blocks in a row");
        return null;
    } else if (parentHdr.getSealType() == Seal.PROOF_OF_WORK) {
        if (forkUtility.isUnityForkBlock(parentHdr.getNumber())) {
            // this is the first PoS block, use all zeroes as seed, and totalStake / 10 as difficulty
            parentSeed = GENESIS_SEED;
            newDiff = calculateFirstPoSDifficultyAtBlock(parent);
        } else if (forkUtility.isNonceForkBlock(parentHdr.getNumber())) {
            BlockHeader parentStakingBlock = getParent(parentHdr).getHeader();
            parentSeed = ((StakingBlockHeader) parentStakingBlock).getSeedOrProof();
            newDiff = calculateFirstPoSDifficultyAtBlock(parent);
            forkUtility.setNonceForkResetDiff(newDiff);
        } else {
            Block[] blockFamily = repository.getBlockStore().getTwoGenerationBlocksByHashWithInfo(parentHdr.getParentHash());
            Objects.requireNonNull(blockFamily[0]);
            BlockHeader parentStakingBlock = blockFamily[0].getHeader();
            BlockHeader parentStakingBlocksParent = blockFamily[1].getHeader();
            parentSeed = ((StakingBlockHeader) parentStakingBlock).getSeedOrProof();
            newDiff = chainConfiguration.getUnityDifficultyCalculator().calculateDifficulty(parentStakingBlock, parentStakingBlocksParent);
        }
    } else {
        throw new IllegalStateException("Invalid block type");
    }
    long newTimestamp;
    AionAddress coinbaseAddress = new AionAddress(coinbase);
    if (signingPublicKey != null) {
        // Create block template for the external stakers.
        byte[] proofHash = null;
        if (forkUtility.isSignatureSwapForkBlock(parent.getNumber() - 1)) {
            if (!VRF_Ed25519.verify(parentSeed, newSeed, signingPublicKey)) {
                LOG.debug("Seed verification failed! previousProof:{} newProof:{} pKey:{}", ByteUtil.toHexString(parentSeed), ByteUtil.toHexString(newSeed), ByteUtil.toHexString(signingPublicKey));
                return null;
            }
            proofHash = VRF_Ed25519.generateProofHash(newSeed);
        } else if (forkUtility.isSignatureSwapForkActive(parent.getNumber() + 1)) {
            byte[] parentSeedHash = VRF_Ed25519.generateProofHash(parentSeed);
            if (!VRF_Ed25519.verify(parentSeedHash, newSeed, signingPublicKey)) {
                LOG.debug("Seed verification failed! previousProof:{} newProof:{} pKey:{}", ByteUtil.toHexString(parentSeed), ByteUtil.toHexString(newSeed), ByteUtil.toHexString(signingPublicKey));
                return null;
            }
            proofHash = VRF_Ed25519.generateProofHash(newSeed);
        } else {
            if (!ECKeyEd25519.verify(parentSeed, newSeed, signingPublicKey)) {
                LOG.debug("Seed verification failed! previousSeed:{} newSeed:{} pKey:{}", ByteUtil.toHexString(parentSeed), ByteUtil.toHexString(newSeed), ByteUtil.toHexString(signingPublicKey));
                return null;
            }
            if (forkUtility.isNonceForkActive(parentHdr.getNumber() + 1)) {
                // new seed generation
                BlockHeader parentStakingBlock = getParent(parentHdr).getHeader();
                // retrieve components
                parentSeed = ((StakingBlockHeader) parentStakingBlock).getSeedOrProof();
                byte[] signerAddress = new AionAddress(AddressSpecs.computeA0Address(signingPublicKey)).toByteArray();
                ;
                byte[] powMineHash = ((MiningBlock) parent).getHeader().getMineHash();
                byte[] powNonce = ((MiningBlock) parent).getNonce();
                int lastIndex = parentSeed.length + signerAddress.length + powMineHash.length + powNonce.length;
                byte[] concatenated = new byte[lastIndex + 1];
                System.arraycopy(parentSeed, 0, concatenated, 0, parentSeed.length);
                System.arraycopy(signerAddress, 0, concatenated, parentSeed.length, signerAddress.length);
                System.arraycopy(powMineHash, 0, concatenated, parentSeed.length + signerAddress.length, powMineHash.length);
                System.arraycopy(powNonce, 0, concatenated, parentSeed.length + signerAddress.length + powMineHash.length, powNonce.length);
                concatenated[lastIndex] = 0;
                byte[] hash1 = h256(concatenated);
                concatenated[lastIndex] = 1;
                byte[] hash2 = h256(concatenated);
                sealedSeed = new byte[hash1.length + hash2.length];
                System.arraycopy(hash1, 0, sealedSeed, 0, hash1.length);
                System.arraycopy(hash2, 0, sealedSeed, hash1.length, hash2.length);
            }
        }
        AionAddress signingAddress = new AionAddress(AddressSpecs.computeA0Address(signingPublicKey));
        BigInteger stakes = null;
        try {
            stakes = getStakingContractHelper().getEffectiveStake(signingAddress, coinbaseAddress, parent);
        } catch (Exception e) {
            LOG.error("Shutdown due to a fatal error encountered while getting the effective stake.", e);
            System.exit(SystemExitCodes.FATAL_VM_ERROR);
        }
        if (stakes.signum() < 1) {
            LOG.debug("The caller {} with coinbase {} has no stake ", signingAddress.toString(), coinbase.toString());
            return null;
        }
        long newDelta = StakingDeltaCalculator.calculateDelta(proofHash == null ? sealedSeed : proofHash, newDiff, stakes);
        newTimestamp = Long.max(parent.getHeader().getTimestamp() + newDelta, parent.getHeader().getTimestamp() + 1);
    } else {
        newTimestamp = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
        if (parentHdr.getTimestamp() >= newTimestamp) {
            newTimestamp = parentHdr.getTimestamp() + 1;
        }
    }
    StakingBlock block;
    try {
        StakingBlockHeader.Builder headerBuilder = StakingBlockHeader.Builder.newInstance().withParentHash(parent.getHash()).withCoinbase(coinbaseAddress).withNumber(parentHdr.getNumber() + 1).withTimestamp(newTimestamp).withExtraData(minerExtraData).withTxTrieRoot(calcTxTrieRoot(txs)).withEnergyLimit(energyLimitStrategy.getEnergyLimit(parentHdr)).withDifficulty(ByteUtil.bigIntegerToBytes(newDiff, DIFFICULTY_BYTES)).withDefaultStateRoot().withDefaultReceiptTrieRoot().withDefaultLogsBloom().withDefaultSignature().withDefaultSigningPublicKey();
        if (signingPublicKey != null) {
            headerBuilder.withSigningPublicKey(signingPublicKey);
        }
        if (forkUtility.isSignatureSwapForkActive(parentHdr.getNumber() + 1)) {
            headerBuilder.withProof(sealedSeed);
        } else {
            headerBuilder.withSeed(sealedSeed);
        }
        block = new StakingBlock(headerBuilder.build(), txs);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    BigInteger transactionFee = blockPreSeal(parentHdr, block);
    if (transactionFee == null) {
        return null;
    }
    if (signingPublicKey != null) {
        stakingBlockTemplate.putIfAbsent(ByteArrayWrapper.wrap(block.getHeader().getMineHash()), block);
    }
    LOG.debug("GetBlockTemp: {}", block.toString());
    return block;
}
Also used : AionAddress(org.aion.types.AionAddress) StakingBlockHeader(org.aion.zero.impl.types.StakingBlockHeader) MiningBlock(org.aion.zero.impl.types.MiningBlock) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) BigInteger(java.math.BigInteger) Block(org.aion.zero.impl.types.Block) BlockDetailsValidator.isValidBlock(org.aion.zero.impl.valid.BlockDetailsValidator.isValidBlock) GenesisStakingBlock(org.aion.zero.impl.types.GenesisStakingBlock) RetValidPreBlock(org.aion.zero.impl.types.RetValidPreBlock) MiningBlock(org.aion.zero.impl.types.MiningBlock) EventBlock(org.aion.evtmgr.impl.evt.EventBlock) StakingBlock(org.aion.zero.impl.types.StakingBlock) BlockHeader(org.aion.zero.impl.types.BlockHeader) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) StakingBlockHeader(org.aion.zero.impl.types.StakingBlockHeader) GenesisStakingBlock(org.aion.zero.impl.types.GenesisStakingBlock) StakingBlock(org.aion.zero.impl.types.StakingBlock)

Example 82 with AionAddress

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

the class AionBlockchainImpl method balanceRollback.

/**
 * SQ4-142
 * Rollback the balance for the mistake transactions
 */
private void balanceRollback() {
    List<byte[]> rollbackTxHash = CfgAion.inst().getFork().getRollbackTx();
    if (rollbackTxHash == null) {
        LOG.debug("no rollback transaction");
        return;
    }
    int accountDeleted = 0;
    for (byte[] hash : rollbackTxHash) {
        AionTxInfo info = getTransactionInfo(hash);
        if (info == null) {
            throw new IllegalStateException("the database missing the rollback transaction:" + ByteUtil.toHexString(hash) + "\n" + "Please re-sync your database.");
        }
        AionAddress sender = info.getReceipt().getTransaction().getSenderAddress();
        AionAddress receiver = info.getReceipt().getTransaction().getDestinationAddress();
        BigInteger balance = info.getReceipt().getTransaction().getValueBI();
        LOG.debug("sender {}, receiver {}, balance {}", sender, receiver, balance);
        AccountState stateReceiver = track.getAccountState(receiver);
        if (stateReceiver == null) {
            throw new IllegalStateException("missing receiver's state of the rollback transaction: " + receiver);
        }
        if (stateReceiver.isDeleted()) {
            throw new IllegalStateException("the receiver's state has been deleted: " + receiver);
        }
        if (stateReceiver.getBalance().compareTo(balance) >= 0) {
            track.addBalance(sender, balance);
            track.addBalance(receiver, balance.negate());
        } else {
            throw new IllegalStateException("the receiver state of the balance cannot be negative: " + receiver);
        }
        if (stateReceiver.getBalance().equals(ZERO)) {
            track.deleteAccount(receiver);
            accountDeleted++;
            LOG.debug("deletedAccount: {}", receiver);
        }
    }
    LOG.debug("rollback transactions: {}, account deleted: {}", rollbackTxHash.size(), accountDeleted);
}
Also used : AionAddress(org.aion.types.AionAddress) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) BigInteger(java.math.BigInteger) AccountState(org.aion.base.AccountState)

Example 83 with AionAddress

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

the class AionBlockchainImpl method applyBlock.

private AionBlockSummary applyBlock(Block block) {
    long saveTime = System.nanoTime();
    List<AionTxReceipt> receipts = new ArrayList<>();
    List<AionTxExecSummary> summaries = new ArrayList<>();
    if (!block.getTransactionsList().isEmpty()) {
        // might apply the block before the 040 fork point.
        boolean fork040Enable = forkUtility.is040ForkActive(block.getNumber());
        if (fork040Enable) {
            TransactionTypeRule.allowAVMContractTransaction();
        }
        if (forkUtility.isSignatureSwapForkActive(block.getNumber())) {
            HashUtil.setAfterSignatureSwap();
        } else {
            HashUtil.setBeforeSignatureSwap();
        }
        try {
            // Booleans moved out here so their meaning is explicit.
            boolean isLocalCall = false;
            boolean incrementSenderNonce = true;
            boolean checkBlockEnergyLimit = false;
            List<AionTxExecSummary> executionSummaries = BulkExecutor.executeAllTransactionsInBlock(block.getDifficulty(), block.getNumber(), block.getTimestamp(), block.getNrgLimit(), block.getCoinbase(), block.getTransactionsList(), track, isLocalCall, incrementSenderNonce, fork040Enable, checkBlockEnergyLimit, LOGGER_VM, getPostExecutionWorkForApplyBlock(repository), executionTypeForAVM, cachedBlockNumberForAVM, forkUtility.isUnityForkActive(block.getNumber()), forkUtility.isSignatureSwapForkActive(block.getNumber()));
            // Check for rejected transaction already included in the chain.
            if (isException(block.getNumber())) {
                for (AionTxExecSummary summary : executionSummaries) {
                    if (summary.isRejected()) {
                        AionTxReceipt receipt = summary.getReceipt();
                        receipt.setNrgUsed(receipt.getTransaction().getEnergyLimit());
                    }
                }
            }
            for (AionTxExecSummary summary : executionSummaries) {
                receipts.add(summary.getReceipt());
                summaries.add(summary);
            }
        } catch (VmFatalException e) {
            LOG.error("Shutdown due to a VM fatal error.", e);
            System.exit(SystemExitCodes.FATAL_VM_ERROR);
        }
    }
    Map<AionAddress, BigInteger> rewards = addReward(block);
    return new AionBlockSummary(block, rewards, receipts, summaries);
}
Also used : AionAddress(org.aion.types.AionAddress) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) BigInteger(java.math.BigInteger) AionTxReceipt(org.aion.base.AionTxReceipt)

Example 84 with AionAddress

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

the class AionBlockchainImpl method generatePreBlock.

/**
 * For generating the necessary transactions for a block
 *
 * @param block
 * @return
 */
private RetValidPreBlock generatePreBlock(Block block) {
    long saveTime = System.nanoTime();
    List<AionTxReceipt> receipts = new ArrayList<>();
    List<AionTxExecSummary> summaries = new ArrayList<>();
    List<AionTransaction> transactions = new ArrayList<>();
    if (!block.getTransactionsList().isEmpty()) {
        boolean fork040Enable = forkUtility.is040ForkActive(block.getNumber());
        if (fork040Enable) {
            TransactionTypeRule.allowAVMContractTransaction();
        }
        try {
            // Booleans moved out here so their meaning is explicit.
            boolean isLocalCall = false;
            boolean incrementSenderNonce = true;
            boolean checkBlockEnergyLimit = true;
            List<AionTxExecSummary> executionSummaries = BulkExecutor.executeAllTransactionsInBlock(block.getDifficulty(), block.getNumber(), block.getTimestamp(), block.getNrgLimit(), block.getCoinbase(), block.getTransactionsList(), track, isLocalCall, incrementSenderNonce, fork040Enable, checkBlockEnergyLimit, LOGGER_VM, getPostExecutionWorkForGeneratePreBlock(repository), BlockCachingContext.PENDING, bestBlock.getNumber(), forkUtility.isUnityForkActive(block.getNumber()), forkUtility.isSignatureSwapForkActive(block.getNumber()));
            for (AionTxExecSummary summary : executionSummaries) {
                if (!summary.isRejected()) {
                    transactions.add(summary.getTransaction());
                    receipts.add(summary.getReceipt());
                    summaries.add(summary);
                }
            }
        } catch (VmFatalException e) {
            LOG.error("Shutdown due to a VM fatal error.", e);
            System.exit(SystemExitCodes.FATAL_VM_ERROR);
        }
    }
    Map<AionAddress, BigInteger> rewards = addReward(block);
    return new RetValidPreBlock(transactions, rewards, receipts, summaries);
}
Also used : AionAddress(org.aion.types.AionAddress) RetValidPreBlock(org.aion.zero.impl.types.RetValidPreBlock) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) AionTransaction(org.aion.base.AionTransaction) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) BigInteger(java.math.BigInteger) AionTxReceipt(org.aion.base.AionTxReceipt)

Example 85 with AionAddress

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

the class TokenBridgeContractTest method testTransferInsufficientValidatorSignatures.

@Test
public void testTransferInsufficientValidatorSignatures() {
    // 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 (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());
    // set relayer
    byte[] callPayload = new AbiEncoder(BridgeFuncSig.SIG_SET_RELAYER.getSignature(), new AddressFVM(members[0].getAddress())).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].getAddress()), 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 = HashUtil.h256("blockHash".getBytes());
    BridgeTransfer[] transfers = new BridgeTransfer[5];
    for (int i = 0; i < 5; 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);
    }
    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);
    // only give 3/5 signatures
    byte[][] signatures = new byte[3][];
    signatures[0] = members[0].sign(payloadHash).toBytes();
    signatures[1] = members[1].sign(payloadHash).toBytes();
    signatures[2] = members[1].sign(payloadHash).toBytes();
    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) {
        // add incorrect signatures, copies [0:32] for all chunks
        sigChunk1.add(new AddressFVM(Arrays.copyOfRange(sig, 0, 32)));
        sigChunk2.add(new AddressFVM(Arrays.copyOfRange(sig, 0, 32)));
        sigChunk3.add(new AddressFVM(Arrays.copyOfRange(sig, 0, 32)));
    }
    callPayload = new AbiEncoder(BridgeFuncSig.SIG_SUBMIT_BUNDLE.getSignature(), new AddressFVM(blockHash), sourceTransactionList, addressList, uintList, sigChunk1, sigChunk2, sigChunk3).encodeBytes();
    // input will include 5 transfers and 3 validators with incorrect signatures
    transferResult = this.contract.execute(callPayload, DEFAULT_NRG);
    // / VERIFICATION
    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 : Uint128FVM(org.aion.zero.impl.precompiled.encoding.Uint128FVM) AionAddress(org.aion.types.AionAddress) 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) BridgeTransfer(org.aion.precompiled.contracts.ATB.BridgeTransfer) ListFVM(org.aion.zero.impl.precompiled.encoding.ListFVM) PrecompiledTransactionResult(org.aion.precompiled.PrecompiledTransactionResult) PrecompiledTransactionContext(org.aion.precompiled.type.PrecompiledTransactionContext) Test(org.junit.Test)

Aggregations

AionAddress (org.aion.types.AionAddress)491 Test (org.junit.Test)364 AionTransaction (org.aion.base.AionTransaction)275 BigInteger (java.math.BigInteger)194 ImportResult (org.aion.zero.impl.core.ImportResult)110 AionTxExecSummary (org.aion.base.AionTxExecSummary)97 RepositoryCache (org.aion.base.db.RepositoryCache)90 MiningBlock (org.aion.zero.impl.types.MiningBlock)89 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)80 ArrayList (java.util.ArrayList)76 ECKey (org.aion.crypto.ECKey)74 AionTxReceipt (org.aion.base.AionTxReceipt)60 Block (org.aion.zero.impl.types.Block)60 AccountState (org.aion.base.AccountState)56 HashMap (java.util.HashMap)42 DataWord (org.aion.util.types.DataWord)39 PrecompiledTransactionResult (org.aion.precompiled.PrecompiledTransactionResult)36 InternalTransaction (org.aion.types.InternalTransaction)32 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)29 BlockContext (org.aion.zero.impl.types.BlockContext)29