/// <summary> /// /// </summary> /// <param name="block"></param> /// <returns></returns> public async Task <VerifyResult> BlockExists(Block block) { Guard.Argument(block, nameof(block)).NotNull(); var hasSeen = await _unitOfWork.HashChainRepository.GetAsync(block.ToIdentifier()); return(hasSeen != null ? VerifyResult.AlreadyExists : VerifyResult.Succeed); }
/// <summary> /// /// </summary> /// <param name="block"></param> /// <returns></returns> public async Task <VerifyResult> VerifyMerkel(Block block) { Guard.Argument(block, nameof(block)).NotNull(); var height = await _unitOfWork.HashChainRepository.CountAsync() - 1; var prevBlock = await _unitOfWork.HashChainRepository.GetAsync(x => new ValueTask <bool>(x.Height == (ulong)height)); if (prevBlock == null) { _logger.Here().Error("No previous block available"); return(VerifyResult.UnableToVerify); } var merkelRoot = BlockHeader.ToMerkelRoot(prevBlock.BlockHeader.MerkleRoot, block.Txs); var verifyMerkel = merkelRoot.Xor(block.BlockHeader.MerkleRoot); return(verifyMerkel ? VerifyResult.Succeed : VerifyResult.UnableToVerify); }
/// <summary> /// /// </summary> /// <param name="block"></param> /// <returns></returns> public async Task <VerifyResult> VerifyBlockHash(Block block) { Guard.Argument(block, nameof(block)).NotNull(); using var hasher = Hasher.New(); var height = await _unitOfWork.HashChainRepository.CountAsync() - 1; var prevBlock = await _unitOfWork.HashChainRepository.GetAsync(x => new ValueTask <bool>(x.Height == (ulong)height)); if (prevBlock == null) { _logger.Here().Error("No previous block available"); return(VerifyResult.UnableToVerify); } hasher.Update(prevBlock.Hash); hasher.Update(block.ToHash()); var hash = hasher.Finalize(); var verifyHasher = hash.HexToByte().Xor(block.Hash); return(verifyHasher ? VerifyResult.Succeed : VerifyResult.UnableToVerify); }
/// <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); }