Search in sources :

Example 1 with StakingBlockHeader

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

the class StakingBlockTimeStampRule method validate.

@Override
public boolean validate(BlockHeader header, BlockHeader dependency, List<RuleError> errors, Object stake) {
    if (!(header instanceof StakingBlockHeader)) {
        BlockHeaderValidatorUtil.addError("Invalid header type", this.getClass(), errors);
        return false;
    }
    if (dependency instanceof StakingBlockHeader) {
        BlockHeaderValidatorUtil.addError("Invalid parent header type", this.getClass(), errors);
        return false;
    }
    if (stake == null) {
        BlockHeaderValidatorUtil.addError("The stake can not be null", this.getClass(), errors);
        return false;
    }
    if (!(stake instanceof BigInteger)) {
        BlockHeaderValidatorUtil.addError("Invalid stake object type", this.getClass(), errors);
        return false;
    }
    long parentTimeStamp = dependency.getTimestamp();
    BigInteger stakes = (BigInteger) stake;
    if (stakes.signum() < 1) {
        return false;
    }
    long timeStamp = header.getTimestamp();
    BigInteger blockDifficulty = header.getDifficultyBI();
    byte[] seed = ((StakingBlockHeader) header).getSeedOrProof();
    if (seed.length == StakingBlockHeader.PROOF_LENGTH) {
        seed = VRF_Ed25519.generateProofHash(seed);
    }
    BigInteger dividend = new BigInteger(1, HashUtil.h256(seed));
    FixedPoint logDifference = logBoundary.subtract(LogApproximator.log(dividend));
    BigInteger delta = logDifference.multiplyInteger(blockDifficulty).toBigInteger().divide(stakes);
    long offset = max(delta.longValueExact(), 1);
    if (timeStamp != (parentTimeStamp + offset)) {
        BlockHeaderValidatorUtil.addError(formatError(timeStamp, parentTimeStamp, offset), this.getClass(), errors);
        return false;
    }
    return true;
}
Also used : FixedPoint(org.aion.util.math.FixedPoint) StakingBlockHeader(org.aion.zero.impl.types.StakingBlockHeader) BigInteger(java.math.BigInteger)

Example 2 with StakingBlockHeader

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

the class SignatureRule method validate.

@Override
public boolean validate(BlockHeader header, List<RuleError> errors) {
    if (!(header instanceof StakingBlockHeader)) {
        BlockHeaderValidatorUtil.addError("Invalid header type", this.getClass(), errors);
        return false;
    }
    StakingBlockHeader stakingBlockHeader = (StakingBlockHeader) header;
    byte[] mineHash = header.getMineHash();
    byte[] pk = stakingBlockHeader.getSigningPublicKey();
    byte[] sig = stakingBlockHeader.getSignature();
    if (!ECKeyEd25519.verify(mineHash, sig, pk)) {
        BlockHeaderValidatorUtil.addError(formatError(mineHash, ByteUtil.merge(pk, sig)), this.getClass(), errors);
        return false;
    }
    return true;
}
Also used : StakingBlockHeader(org.aion.zero.impl.types.StakingBlockHeader)

Example 3 with StakingBlockHeader

use of org.aion.zero.impl.types.StakingBlockHeader 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)

Aggregations

StakingBlockHeader (org.aion.zero.impl.types.StakingBlockHeader)3 BigInteger (java.math.BigInteger)2 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)1 AionAddress (org.aion.types.AionAddress)1 FixedPoint (org.aion.util.math.FixedPoint)1 Block (org.aion.zero.impl.types.Block)1 BlockHeader (org.aion.zero.impl.types.BlockHeader)1 GenesisStakingBlock (org.aion.zero.impl.types.GenesisStakingBlock)1 MiningBlock (org.aion.zero.impl.types.MiningBlock)1 MiningBlockHeader (org.aion.zero.impl.types.MiningBlockHeader)1 RetValidPreBlock (org.aion.zero.impl.types.RetValidPreBlock)1 StakingBlock (org.aion.zero.impl.types.StakingBlock)1 BlockDetailsValidator.isValidBlock (org.aion.zero.impl.valid.BlockDetailsValidator.isValidBlock)1 VmFatalException (org.aion.zero.impl.vm.common.VmFatalException)1