private bool SubmitBlock(BlockMsg block) { try { var blockData = Base16.Encode(block.Serialize()); //TODO 测试 数据 //LogHelper.Warn("SubmitBlock Src >> BlockMsg : " + Newtonsoft.Json.JsonConvert.SerializeObject(block) + " ; Base16AfterSerialize : "+blockData); this.SendRpcRequest("SubmitBlock", new object[] { blockData }); return(true); } catch (Exception ex) { LogHelper.Error(ex.ToString()); throw ex; } }
public bool VerifyBlock(BlockMsg newBlock) { if (this.exists(newBlock.Header.Hash)) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HAS_BEEN_EXISTED); } if (newBlock.Header.Hash != newBlock.Header.GetHash()) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HASH_ERROR); } var blockComponent = new BlockComponent(); var previousBlock = this.GetBlockMsgByHash(newBlock.Header.PreviousBlockHash); if (newBlock.Header.Height > 0 && previousBlock == null) { throw new CommonException(ErrorCode.Engine.Block.Verify.PREV_BLOCK_NOT_EXISTED); } if ((newBlock.Header.Timestamp > Time.EpochTime && (newBlock.Header.Timestamp - Time.EpochTime) > 2 * 60 * 60 * 1000) || (previousBlock != null && newBlock.Header.Timestamp <= previousBlock.Header.Timestamp)) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_TIME_IS_ERROR); } if (newBlock.Serialize().Length > BlockSetting.MAX_BLOCK_SIZE) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIZE_LARGE_THAN_LIMIT); } var txComponent = new TransactionComponent(); var newBlockReward = POC.GetNewBlockReward(newBlock.Header.Height); var prevStepBlock = GetBlockMsgByHeight(newBlock.Header.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1); var minerInfo = string.Empty; if (newBlock.Transactions.Count > 0) { var coinbase = newBlock.Transactions[0]; var totalFee = 0L; minerInfo = Encoding.UTF8.GetString(Base16.Decode(coinbase.Inputs[0].UnlockScript)).Split("`")[0]; if (newBlock.Transactions.Count > 1) { for (int i = 1; i < newBlock.Transactions.Count; i++) { long fee; if (txComponent.VerifyTransaction(newBlock.Transactions[i], out fee)) { totalFee += fee; } else { return(false); } } } if (coinbase.Inputs.Count != 1 || coinbase.Outputs.Count != 1 || coinbase.Inputs[0].OutputTransactionHash != Base16.Encode(HashHelper.EmptyHash())) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_FORMAT_ERROR); } else { var output = coinbase.Outputs[0]; if (output.Amount > BlockSetting.OUTPUT_AMOUNT_MAX) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_EXCEEDED_THE_LIMIT); } if (!Script.VerifyLockScriptFormat(output.LockScript)) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.SCRIPT_FORMAT_ERROR); } if (output.Amount != (totalFee + newBlockReward)) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_OUTPUT_AMOUNT_ERROR); } } } var pool = new MiningPoolComponent().GetMiningPoolByName(minerInfo); if (pool == null) { throw new CommonException(ErrorCode.Engine.Block.Verify.MINING_POOL_NOT_EXISTED); } if (!POC.VerifyBlockSignature(newBlock.Header.PayloadHash, newBlock.Header.BlockSignature, pool.PublicKey)) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIGNATURE_IS_ERROR); } long previousBlockHeight = -1; long previousBlockBits = -1; if (previousBlock != null) { previousBlockHeight = previousBlock.Header.Height; previousBlockBits = previousBlock.Header.Bits; } if (POC.CalculateBaseTarget(newBlock.Header.Height, previousBlock, prevStepBlock) != newBlock.Header.Bits) { throw new CommonException(ErrorCode.Engine.Block.Verify.BITS_IS_WRONG); } var targetResult = POC.CalculateTargetResult(newBlock); if (POC.Verify(newBlock.Header.Bits, targetResult)) { return(true); } else { throw new CommonException(ErrorCode.Engine.Block.Verify.POC_VERIFY_FAIL); } }
public bool VerifyBlock(BlockMsg newBlock) { if (this.exists(newBlock.Header.Hash)) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HAS_BEEN_EXISTED); } if (newBlock.Header.Hash != newBlock.Header.GetHash()) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HASH_ERROR); } var blockComponent = new BlockComponent(); var previousBlock = this.GetBlockMsgByHash(newBlock.Header.PreviousBlockHash); if (newBlock.Header.Height > 0 && previousBlock == null) { throw new CommonException(ErrorCode.Engine.Block.Verify.PREV_BLOCK_NOT_EXISTED); } if ((newBlock.Header.Timestamp > Time.EpochTime && (newBlock.Header.Timestamp - Time.EpochTime) > 2 * 60 * 60 * 1000) || (previousBlock != null && newBlock.Header.Timestamp <= previousBlock.Header.Timestamp)) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_TIME_IS_ERROR); } if (newBlock.Serialize().Length > BlockSetting.MAX_BLOCK_SIZE) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIZE_LARGE_THAN_LIMIT); } var work = new POW(newBlock.Header.Height); var txComponent = new TransactionComponent(); if (newBlock.Transactions.Count > 0) { var coinbase = newBlock.Transactions[0]; var reward = work.GetNewBlockReward(); var totalFee = 0L; if (newBlock.Transactions.Count > 1) { for (int i = 1; i < newBlock.Transactions.Count; i++) { long fee; if (txComponent.VerifyTransaction(newBlock.Transactions[i], out fee)) { totalFee += fee; } else { return(false); } } } if (coinbase.Inputs.Count != 1 || coinbase.Outputs.Count != 1 || coinbase.Inputs[0].OutputTransactionHash != Base16.Encode(HashHelper.EmptyHash())) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_FORMAT_ERROR); } else { var output = coinbase.Outputs[0]; if (output.Amount > BlockSetting.OUTPUT_AMOUNT_MAX) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_EXCEEDED_THE_LIMIT); } if (!Script.VerifyLockScriptFormat(output.LockScript)) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.SCRIPT_FORMAT_ERROR); } if (output.Amount != (totalFee + reward)) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_OUTPUT_AMOUNT_ERROR); } } } var prev4032Block = this.GetBlockMsgByHeight(newBlock.Header.Height - POW.DiffiucltyAdjustStep); long previousBlockHeight = -1; long previousBlockBits = -1; if (previousBlock != null) { previousBlockHeight = previousBlock.Header.Height; previousBlockBits = previousBlock.Header.Bits; } if (work.CalculateNextWorkTarget(previousBlockHeight, previousBlockBits, prev4032Block) != newBlock.Header.Bits) { throw new CommonException(ErrorCode.Engine.Block.Verify.BITS_IS_WRONG); } var hashResult = this.GetMiningWorkResult(newBlock); if (work.Verify(newBlock.Header.Bits, hashResult)) { return(true); } else { throw new CommonException(ErrorCode.Engine.Block.Verify.POW_VERIFY_FAIL); } }
public bool VerifyBlockBasic(BlockMsg newBlock) { if (newBlock.Header.Hash != newBlock.Header.GetHash()) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HASH_ERROR); } bool hasPreviousBlock = false; long previousBlockTimestamp = -1; long previousBlockBits = -1; long previousBlockHeight = newBlock.Header.Height - 1; var cacheBlockKey = $"{newBlock.Header.Hash}_{newBlock.Header.Height - 1}"; var previousBlockMsg = BlockDac.Default.SelectByHash(newBlock.Header.PreviousBlockHash); if (previousBlockMsg != null) { hasPreviousBlock = true; previousBlockTimestamp = previousBlockMsg.Header.Timestamp; previousBlockBits = previousBlockMsg.Header.Bits; } else { var previousBlock = BlockDac.Default.SelectByHash(newBlock.Header.PreviousBlockHash); hasPreviousBlock = previousBlock != null; if (hasPreviousBlock) { previousBlockTimestamp = previousBlock.Header.Timestamp; previousBlockBits = previousBlock.Header.Bits; } } if (newBlock.Header.Height > 0 && !hasPreviousBlock) { throw new CommonException(ErrorCode.Engine.Block.Verify.PREV_BLOCK_NOT_EXISTED); } if ((newBlock.Header.Timestamp - Time.EpochTime) > 2 * 60 * 60 * 1000 || (hasPreviousBlock && newBlock.Header.Timestamp <= previousBlockTimestamp)) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_TIME_IS_ERROR); } if (newBlock.Serialize().Length > Consensus.BlockSetting.MAX_BLOCK_SIZE) { throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIZE_LARGE_THAN_LIMIT); } BlockMsg prevStepBlock = null; if (newBlock.Header.Height >= POC.DIFFIUCLTY_ADJUST_STEP) { var prevStepHeight = 0L; if (!GlobalParameters.IsTestnet && newBlock.Header.Height <= POC.DIFFICULTY_CALCULATE_LOGIC_ADJUST_HEIGHT) { prevStepHeight = newBlock.Header.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1; } else { prevStepHeight = newBlock.Header.Height - POC.DIFFIUCLTY_ADJUST_STEP; } prevStepBlock = BlockDac.Default.SelectByHeight(prevStepHeight); } //区块必须包含交易,否则错误 if (newBlock.Transactions == null || newBlock.Transactions.Count == 0) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.NOT_FOUND_COINBASE); } //第一个一定是coinbase,奖励+手续费 var coinbase = newBlock.Transactions[0]; //校验打包区块的矿池是否经过验证 var minerInfo = Encoding.UTF8.GetString(Base16.Decode(coinbase.Inputs[0].UnlockScript)).Split("`")[0]; var pool = MiningPoolComponent.CurrentMiningPools.FirstOrDefault(x => x.Name == minerInfo); if (pool == null) { throw new CommonException(ErrorCode.Engine.Block.Verify.MINING_POOL_NOT_EXISTED); } //校验区块的签名信息 if (!POC.VerifyBlockSignature(newBlock.Header.PayloadHash, newBlock.Header.BlockSignature, pool.PublicKey)) { LogHelper.Warn($"PayloadHash::{newBlock.Header.PayloadHash}"); LogHelper.Warn($"BlockSignature::{newBlock.Header.BlockSignature}"); LogHelper.Warn($"PublicKey::{pool.PublicKey}"); throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIGNATURE_IS_ERROR); } if (POC.CalculateBaseTarget(newBlock.Header.Height, previousBlockBits, previousBlockTimestamp, prevStepBlock) != newBlock.Header.Bits) { throw new CommonException(ErrorCode.Engine.Block.Verify.BITS_IS_WRONG); } var targetResult = POC.CalculateTargetResult(newBlock); if (newBlock.Header.Height == 17687 || POC.Verify(newBlock.Header.Bits, targetResult)) { return(true); } else { throw new CommonException(ErrorCode.Engine.Block.Verify.POC_VERIFY_FAIL); } }