Beispiel #1
0
        /// <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;
        }