/// <summary> /// 验证签名 /// </summary> private async Task <bool> VerifySign() { var config = await _configProvider.GetConfigAsync(); var signManager = new SignManager(new SignKey(config.PrivateKey, config.PublicKey), CreateVerifyBuilder()); return(signManager.Verify(Sign)); }
public static void VerifyTransaction(Transaction tx, DateTime timestamp, ulong coinbase = 0) { if (tx.TimeStamp > timestamp || !(coinbase == 0 ^ tx.Inputs.Count == 0)) { throw new ArgumentException(); } var hash = HashUtil.ComputeTransactionSignHash(JsonSerializer.Serialize(tx)); //Input check var inSum = coinbase; foreach (var input in tx.Inputs) { var chainTxs = Chain.SelectMany(x => x.Transactions); //Input Verify var transactions = chainTxs as Transaction[] ?? chainTxs.ToArray(); var prevOutTx = transactions .First(x => x.Id.Bytes == input.TransactionId.Bytes)? .Outputs[input.OutputIndex]; var verified = prevOutTx != null && SignManager.Verify(hash, input.Signature, input.PublicKey, prevOutTx.PublicKeyHash); //utxo check ブロックの長さに比例してコストが上がってしまう問題アリ var utxoUsed = transactions.SelectMany(x => x.Inputs).Any(ipt => ipt.TransactionId.Bytes != input.TransactionId.Bytes); var redeemable = prevOutTx.PublicKeyHash.IsEqual(HashUtil.RIPEMD_SHA256(input.PublicKey)); inSum = checked (inSum + prevOutTx.Amount); if (!verified || utxoUsed || !redeemable) { throw new ArgumentException(); } } ulong outSum = 0; foreach (var output in tx.Outputs) { if (output.PublicKeyHash is null || output.Amount <= 0) { throw new ArgumentException(); } outSum = checked (outSum + output.Amount); } if (outSum > inSum) { throw new ArgumentException(); } tx.TransactionFee = inSum - outSum; }