Search in sources :

Example 6 with BlockHeader

use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.

the class SyncHeaderRequestManagerTest method test_missingHeadersTrieRoot.

@Test
public void test_missingHeadersTrieRoot() {
    List<BlockHeader> list = mock(List.class);
    when(list.size()).thenReturn(10);
    BlockHeader header = mock(BlockHeader.class);
    when(header.getTxTrieRootWrapper()).thenReturn(EMPTY_TRIE_HASH);
    when(list.get(0)).thenReturn(header);
    srm.storeHeaders(1, list);
    assertThat(srm.matchAndDropHeaders(1, 10, ByteArrayWrapper.wrap(new byte[32]))).isNull();
}
Also used : BlockHeader(org.aion.zero.impl.types.BlockHeader) Test(org.junit.Test)

Example 7 with BlockHeader

use of org.aion.zero.impl.types.BlockHeader 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 8 with BlockHeader

use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.

the class AionBlockchainImpl method getListOfHeadersStartFrom.

/**
 * Returns up to limit headers found with following search parameters
 *
 * @param blockNumber Identifier of start block, by number
 * @param limit Maximum number of headers in return
 * @return {@link MiningBlockHeader}'s list or empty list if none found
 */
@Override
public List<BlockHeader> getListOfHeadersStartFrom(long blockNumber, int limit) {
    if (limit <= 0) {
        return emptyList();
    }
    // identifying block we'll move from
    Block startBlock = getBlockByNumber(blockNumber);
    // if nothing found on main chain, return empty array
    if (startBlock == null) {
        return emptyList();
    }
    List<BlockHeader> headers;
    long bestNumber = bestBlock.getNumber();
    headers = getContinuousHeaders(bestNumber, blockNumber, limit);
    return headers;
}
Also used : 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)

Example 9 with BlockHeader

use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.

the class SyncMgrTest method testRequestBodies_withFilteringOnBlockHash.

@Test
public void testRequestBodies_withFilteringOnBlockHash() {
    BlockHeader header = mock(BlockHeader.class);
    when(header.getNumber()).thenReturn(100L);
    byte[] hash = Hex.decode("6fd8dae3304a9864f460ec7aec21bc94e14e34876e5dddd0a74d9c68ac7bc9ed");
    when(header.getHash()).thenReturn(hash);
    when(header.getTxTrieRootWrapper()).thenReturn(EMPTY_TRIE_HASH);
    List<BlockHeader> list = new ArrayList<>();
    list.add(header);
    syncMgr.syncHeaderRequestManager.storeHeaders(1, list);
    syncMgr.importedBlockHashes.put(ByteArrayWrapper.wrap(hash), true);
    syncMgr.requestBodies(1, "peer1");
    // ensure that 1 request was sent
    verify(p2pMgr, never()).send(anyInt(), anyString(), any(ReqBlocksBodies.class));
    assertThat(syncMgr.syncHeaderRequestManager.matchAndDropHeaders(1, 1, EMPTY_TRIE_HASH)).isNull();
}
Also used : ArrayList(java.util.ArrayList) BlockHeader(org.aion.zero.impl.types.BlockHeader) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) ReqBlocksBodies(org.aion.zero.impl.sync.msg.ReqBlocksBodies) Test(org.junit.Test)

Example 10 with BlockHeader

use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.

the class SyncMgrTest method testValidateAndAddHeaders_withImportedBlocks.

@Test
public void testValidateAndAddHeaders_withImportedBlocks() {
    int nodeId = 1;
    String displayId = "peer1";
    List<BlockHeader> importedBlocks = new ArrayList<>();
    importedBlocks.add(consecutiveHeaders.get(0));
    importedBlocks.add(consecutiveHeaders.get(1));
    syncMgr.importedBlockHashes.put(importedBlocks.get(0).getHashWrapper(), true);
    syncMgr.importedBlockHashes.put(importedBlocks.get(1).getHashWrapper(), true);
    List<BlockHeader> newHeaders = new ArrayList<>();
    newHeaders.add(consecutiveHeaders.get(2));
    newHeaders.add(consecutiveHeaders.get(3));
    newHeaders.add(consecutiveHeaders.get(4));
    List<BlockHeader> headers = new ArrayList<>();
    headers.addAll(importedBlocks);
    headers.addAll(newHeaders);
    syncMgr.validateAndAddHeaders(nodeId, displayId, headers);
    verify(p2pMgr, never()).errCheck(nodeId, displayId);
    // Check that the sequential subset of headers was stored.
    assertThat(syncMgr.syncHeaderRequestManager.matchAndDropHeaders(nodeId, importedBlocks.size(), importedBlocks.get(0).getTxTrieRootWrapper())).isNull();
    assertThat(syncMgr.syncHeaderRequestManager.matchAndDropHeaders(nodeId, headers.size(), headers.get(0).getTxTrieRootWrapper())).isNull();
    List<BlockHeader> stored = syncMgr.syncHeaderRequestManager.matchAndDropHeaders(nodeId, newHeaders.size(), newHeaders.get(0).getTxTrieRootWrapper());
    assertThat(stored.size()).isEqualTo(newHeaders.size());
    assertThat(stored).containsAllIn(newHeaders);
}
Also used : ArrayList(java.util.ArrayList) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) BlockHeader(org.aion.zero.impl.types.BlockHeader) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) Test(org.junit.Test)

Aggregations

BlockHeader (org.aion.zero.impl.types.BlockHeader)29 Test (org.junit.Test)18 ArrayList (java.util.ArrayList)17 MiningBlockHeader (org.aion.zero.impl.types.MiningBlockHeader)14 ReqBlocksBodies (org.aion.zero.impl.sync.msg.ReqBlocksBodies)8 Block (org.aion.zero.impl.types.Block)7 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)4 BigInteger (java.math.BigInteger)3 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)3 INode (org.aion.p2p.INode)3 SharedRLPList (org.aion.rlp.SharedRLPList)3 GenesisStakingBlock (org.aion.zero.impl.types.GenesisStakingBlock)3 MiningBlock (org.aion.zero.impl.types.MiningBlock)3 RetValidPreBlock (org.aion.zero.impl.types.RetValidPreBlock)3 StakingBlock (org.aion.zero.impl.types.StakingBlock)3 StakingBlockHeader (org.aion.zero.impl.types.StakingBlockHeader)3 BlockDetailsValidator.isValidBlock (org.aion.zero.impl.valid.BlockDetailsValidator.isValidBlock)3 List (java.util.List)2 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1