/// <summary> /// </summary> /// <param name="block"></param> /// <returns></returns> public async Task <VerifyResult> VerifyBlock(Block block) { Guard.Argument(block, nameof(block)).NotNull(); var verifySloth = VerifySloth(block.BlockPos.Bits, block.BlockPos.VrfSig, block.BlockPos.Nonce.ToStr().ToBytes()); if (verifySloth == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the delay function"); return(verifySloth); } var runningDistribution = await CurrentRunningDistribution(block.BlockPos.Solution); var verifyCoinbase = VerifyCoinbaseTransaction(block.Txs.First().Vout.First(), block.BlockPos.Solution, runningDistribution); if (verifyCoinbase == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the coinbase transaction"); return(verifyCoinbase); } byte[] hash; using (var ts = new TangramStream()) { block.Txs.Skip(1).ForEach(x => { if (block.Height == 0ul) { ts.Append(x.ToStream()); } else { var hasAny = x.Validate(); if (hasAny.Any()) { throw new ArithmeticException("Unable to verify the transaction"); } ts.Append(x.ToStream()); } }); hash = Hasher.Hash(ts.ToArray()).HexToByte(); } var verifyVrfProof = VerifyVrfProof(block.BlockPos.PublicKey, block.BlockPos.VrfProof, hash, block.BlockPos.VrfSig); if (verifyVrfProof == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the Vrf Proof"); return(verifyVrfProof); } var verifySolution = VerifySolution(block.BlockPos.VrfSig, hash, block.BlockPos.Solution); if (verifySolution == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the solution"); return(verifySolution); } var bits = Difficulty(block.BlockPos.Solution, block.Txs.First().Vout.First().A.DivWithNanoTan()); if (block.BlockPos.Bits != bits) { _logger.Here().Fatal("Unable to verify the bits"); return(VerifyResult.UnableToVerify); } var verifyLockTime = VerifyLockTime(new LockTime(Utils.UnixTimeToDateTime(block.BlockHeader.Locktime)), block.BlockHeader.LocktimeScript); if (verifyLockTime == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the block lock time"); return(verifyLockTime); } if (block.BlockHeader.MerkleRoot.Xor(BlockZeroHash) && block.BlockHeader.PrevBlockHash.Xor(Hasher.Hash(BlockZeroPreHash).HexToByte())) { return(VerifyResult.Succeed); } var prevBlock = await _unitOfWork.HashChainRepository.GetAsync(x => new ValueTask <bool>(x.Hash.Xor(block.BlockHeader.PrevBlockHash))); if (prevBlock == null) { _logger.Here().Fatal("Unable to find the previous block"); return(VerifyResult.UnableToVerify); } var verifyPreviousHasher = await VerifyBlockHash(block); if (verifyPreviousHasher == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the block hash"); return(verifyPreviousHasher); } var verifyMerkel = await VerifyMerkel(block); if (verifyMerkel == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the merkel tree"); return(verifyMerkel); } var verifyTransactions = await VerifyTransactions(block.Txs); if (verifyTransactions == VerifyResult.Succeed) { return(VerifyResult.Succeed); } _logger.Here().Fatal("Unable to verify the block transactions"); return(VerifyResult.UnableToVerify); }
/// <summary> /// </summary> /// <param name="blockHeader"></param> /// <returns></returns> public async Task <VerifyResult> VerifyBlockHeader(BlockHeaderProto blockHeader) { Guard.Argument(blockHeader, nameof(blockHeader)).NotNull(); var verifySignature = _signing.VerifySignature(blockHeader.Signature.HexToByte(), blockHeader.PublicKey.HexToByte(), blockHeader.ToFinalStream()); if (verifySignature == false) { _logger.Here().Fatal("Unable to verify the block signature"); return(VerifyResult.UnableToVerify); } var verifySloth = VerifySloth(blockHeader.Bits, blockHeader.VrfSignature.HexToByte(), blockHeader.Nonce.ToBytes(), blockHeader.Sec.ToBytes()); if (verifySloth == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the Verified Delay Function"); return(verifySloth); } var runningDistribution = await CurrentRunningDistribution(blockHeader.Solution); var verifyCoinbase = VerifyCoinbaseTransaction(blockHeader.Transactions.First().Vout.First(), blockHeader.Solution, runningDistribution); if (verifyCoinbase == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the coinbase transaction"); return(verifyCoinbase); } uint256 hash; using (var ts = new TangramStream()) { blockHeader.Transactions.Skip(1).ForEach(x => ts.Append(x.Stream())); hash = Hashes.DoubleSHA256(ts.ToArray()); } var verifySolution = VerifySolution(blockHeader.VrfSignature.HexToByte(), hash.ToBytes(false), blockHeader.Solution); if (verifySolution == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the solution"); return(verifySolution); } var bits = Difficulty(blockHeader.Solution, blockHeader.Transactions.First().Vout.First().A.DivWithNanoTan()); if (blockHeader.Bits != bits) { _logger.Here().Fatal("Unable to verify the bits"); return(VerifyResult.UnableToVerify); } Trie.Put(blockHeader.ToHash(), blockHeader.ToHash()); if (!blockHeader.MerkelRoot.Equals(Trie.GetRootHash().ByteToHex())) { _logger.Here().Fatal("Unable to verify the merkel"); var key = Trie.Get(blockHeader.ToHash()); if (key != null) { Trie.Delete(blockHeader.ToHash()); } return(VerifyResult.UnableToVerify); } var verifyLockTime = VerifyLockTime(new LockTime(Utils.UnixTimeToDateTime(blockHeader.Locktime)), blockHeader.LocktimeScript); if (verifyLockTime == VerifyResult.UnableToVerify) { _logger.Here().Fatal("Unable to verify the block lock time"); return(verifyLockTime); } if (blockHeader.MerkelRoot.HexToByte().Xor(BlockZeroMerkel.HexToByte()) && blockHeader.PrevMerkelRoot.HexToByte().Xor(BlockZeroPreMerkel.HexToByte())) { return(VerifyResult.Succeed); } if (blockHeader.Height == 0) { if (!blockHeader.MerkelRoot.HexToByte().Xor(BlockZeroMerkel.HexToByte()) && !blockHeader.PrevMerkelRoot.HexToByte().Xor(BlockZeroPreMerkel.HexToByte())) { return(VerifyResult.UnableToVerify); } } var prevBlock = await _unitOfWork.HashChainRepository.GetAsync(x => new ValueTask <bool>(x.MerkelRoot.Equals(blockHeader.PrevMerkelRoot))); if (prevBlock == null) { _logger.Here().Fatal("Unable to find the previous block"); return(VerifyResult.UnableToVerify); } var verifyTransactions = await VerifyTransactions(blockHeader.Transactions); if (verifyTransactions == VerifyResult.Succeed) { return(VerifyResult.Succeed); } _logger.Here().Fatal("Unable to verify the block transactions"); return(VerifyResult.UnableToVerify); }