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;
        }
        public Transaction ToSignedTransaction(byte[] privateKey, byte[] publicKey)
        {
            _transaction.TimeStamp = DateTime.UtcNow;
            _transaction.Id        = null;
            foreach (var inEntry in Inputs)
            {
                inEntry.PublicKey = null;
                inEntry.Signature = null;
            }
            var hash      = HashUtil.ComputeTransactionSignHash(JsonSerializer.Serialize(_transaction));
            var signature = SignManager.Signature(hash, privateKey, publicKey);

            foreach (var inEntry in Inputs)
            {
                inEntry.PublicKey = publicKey;
                inEntry.Signature = signature;
            }
            var txData = JsonSerializer.Serialize(_transaction);
            var txHash = HashUtil.DoubleSHA256(txData);

            _transaction.Id = new HexString(txHash);
            return(_transaction);
        }