Exemple #1
0
        public static void SignAndShowInformation(Transaction tx)
        {
            if (tx == null)
            {
                MessageBox.Show(Strings.InsufficientFunds);
                return;
            }
            SignatureContext context;

            try
            {
                context = new SignatureContext(tx);
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show(Strings.UnsynchronizedBlock);
                return;
            }
            Program.CurrentWallet.Sign(context);
            if (context.Completed)
            {
                context.Verifiable.Scripts = context.GetScripts();
                Program.CurrentWallet.SaveTransaction(tx);
                Program.LocalNode.Relay(tx);
                InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle);
            }
            else
            {
                InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle);
            }
        }
Exemple #2
0
        public static void SignAndShowInformation(Transaction tx)
        {
            if (tx == null)
            {
                MessageBox.Show("余额不足以支付系统费用。");
                return;
            }
            SignatureContext context;

            try
            {
                context = new SignatureContext(tx);
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show("钱包余额不足,或区块链未同步完成,无法发送该交易。");
                return;
            }
            Program.CurrentWallet.Sign(context);
            if (context.Completed)
            {
                context.Signable.Scripts = context.GetScripts();
                Program.LocalNode.Relay(tx);
                InformationBox.Show(tx.Hash.ToString(), "交易已发送,这是交易编号(TXID):", "交易成功");
            }
            else
            {
                InformationBox.Show(context.ToString(), "交易构造完成,但没有足够的签名:", "签名不完整");
            }
        }
Exemple #3
0
 private void CheckSignatures()
 {
     if (context.Signatures.Count(p => p != null) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p)))
     {
         Contract         contract = Contract.CreateMultiSigContract(context.Validators[context.MyIndex].EncodePoint(true).ToScriptHash(), context.M, context.Validators);
         Block            block    = context.MakeHeader();
         SignatureContext sc       = new SignatureContext(block);
         for (int i = 0, j = 0; i < context.Validators.Length && j < context.M; i++)
         {
             if (context.Signatures[i] != null)
             {
                 sc.AddSignature(contract, context.Validators[i], context.Signatures[i]);
                 j++;
             }
         }
         sc.Verifiable.Scripts = sc.GetScripts();
         block.Transactions    = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray();
         Log($"relay block: {block.Hash}");
         if (!localNode.Relay(block))
         {
             Log($"reject block: {block.Hash}");
         }
         context.State |= ConsensusState.BlockSent;
     }
 }
Exemple #4
0
 private void 资产分发IToolStripMenuItem_Click(object sender, EventArgs e)
 {
     using (IssueDialog dialog = new IssueDialog())
     {
         if (dialog.ShowDialog() != DialogResult.OK)
         {
             return;
         }
         IssueTransaction tx = dialog.GetTransaction();
         if (tx == null)
         {
             return;
         }
         //TODO: 检查是否符合规则,如是否超过总量、分发方式是否符合约定等;
         SignatureContext context = new SignatureContext(tx);
         Program.CurrentWallet.Sign(context);
         if (context.Completed)
         {
             context.Signable.Scripts = context.GetScripts();
             InformationBox.Show(context.Signable.ToArray().ToHexString(), "分发交易构造完成,并已完整签名,可以广播。");
         }
         else
         {
             InformationBox.Show(context.ToString(), "分发交易构造完成,但签名信息还不完整。");
         }
     }
 }
        private void button7_Click(object sender, EventArgs e)
        {
            SignatureContext context = SignatureContext.Parse(textBox8.Text);

            context.Signable.Scripts = context.GetScripts();
            InformationBox.Show(context.Signable.ToArray().ToHexString(), "原始数据:");
        }
Exemple #6
0
        private void button1_Click(object sender, EventArgs e)
        {
            if (textBox1.Text == "")
            {
                MessageBox.Show("必须输入一段含有待签名数据的JSON对象。");
                return;
            }
            SignatureContext context = SignatureContext.Parse(textBox1.Text);

            if (!Program.CurrentWallet.Sign(context))
            {
                MessageBox.Show("没有足够的私钥对数据进行签名。");
                return;
            }
            if (context.Completed)
            {
                context.Signable.Scripts = context.GetScripts();
                textBox2.Text            = context.Signable.ToArray().ToHexString();
                MessageBox.Show("签名完成,该对象的签名信息已经完整,可以广播。");
            }
            else
            {
                textBox2.Text = context.ToString();
                MessageBox.Show("签名完成,但该对象的签名信息还不完整。");
            }
        }
Exemple #7
0
 private void CheckSignatures()
 {
     if (context.Signatures.Count(p => p != null) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p)))
     {
         Log($"{nameof(CheckSignatures)} {context.Signatures.Count(p => p != null)}/{context.M}");
         Contract         contract = Contract.CreateMultiSigContract(context.Miners[context.MinerIndex].EncodePoint(true).ToScriptHash(), context.M, context.Miners);
         Block            block    = context.MakeHeader();
         SignatureContext sc       = new SignatureContext(block);
         for (int i = 0; i < context.Miners.Length; i++)
         {
             if (context.Signatures[i] != null)
             {
                 sc.Add(contract, context.Miners[i], context.Signatures[i]);
             }
         }
         sc.Signable.Scripts = sc.GetScripts();
         block.Transactions  = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray();
         Log($"RelayBlock hash:{block.Hash}");
         if (!LocalNode.Relay(block))
         {
             Log($"failed hash:{block.Hash}");
         }
         context.State |= ConsensusState.BlockSent;
     }
 }
Exemple #8
0
        private void button4_Click(object sender, EventArgs e)
        {
            context.Signable.Scripts = context.GetScripts();
            IInventory inventory = (IInventory)context.Signable;

            Program.LocalNode.Relay(inventory);
            InformationBox.Show(inventory.Hash.ToString(), Strings.RelaySuccessText, Strings.RelaySuccessTitle);
        }
Exemple #9
0
        private void SignAndRelay(ConsensusPayload payload)
        {
            SignatureContext sc = new SignatureContext(payload);

            wallet.Sign(sc);
            sc.Signable.Scripts = sc.GetScripts();
            LocalNode.Relay(payload);
        }
        private async void button8_Click(object sender, EventArgs e)
        {
            SignatureContext context = SignatureContext.Parse(textBox8.Text);

            context.Signable.Scripts = context.GetScripts();
            Inventory inventory = (Inventory)context.Signable;
            await Program.LocalNode.RelayAsync(inventory);

            InformationBox.Show(inventory.Hash.ToString(), "数据广播成功,这是广播数据的散列值:", "广播成功");
        }
Exemple #11
0
        private void button4_Click(object sender, EventArgs e)
        {
            SignatureContext context = SignatureContext.Parse(textBox2.Text);

            context.Verifiable.Scripts = context.GetScripts();
            IInventory inventory = (IInventory)context.Verifiable;

            Program.LocalNode.Relay(inventory);
            InformationBox.Show(inventory.Hash.ToString(), Strings.RelaySuccessText, Strings.RelaySuccessTitle);
            button4.Visible = false;
        }
Exemple #12
0
 public static void ShowInformation(SignatureContext context)
 {
     if (context.Completed)
     {
         context.Signable.Scripts = context.GetScripts();
         Transaction tx = (Transaction)context.Signable;
         Program.LocalNode.Relay(tx);
         InformationBox.Show(tx.Hash.ToString(), "交易已发送,这是交易编号(TXID):", "交易成功");
     }
     else
     {
         InformationBox.Show(context.ToString(), "交易构造完成,但没有足够的签名:", "签名不完整");
     }
 }
Exemple #13
0
        private async Task ShowInformationAsync(SignatureContext context)
        {
            if (context.Completed)
            {
                context.Signable.Scripts = context.GetScripts();
                Transaction tx = (Transaction)context.Signable;
                await Program.LocalNode.RelayAsync(tx);

                InformationBox.Show(tx.Hash.ToString(), "交易已发送,这是交易编号(TXID):", "交易成功");
            }
            else
            {
                InformationBox.Show(context.ToString(), "交易构造完成,但没有足够的签名:", "签名不完整");
            }
        }
Exemple #14
0
        private void SignAndRelay(ConsensusPayload payload)
        {
            SignatureContext sc;

            try
            {
                sc = new SignatureContext(payload);
            }
            catch (InvalidOperationException)
            {
                return;
            }
            wallet.Sign(sc);
            sc.Signable.Scripts = sc.GetScripts();
            LocalNode.Relay(payload);
        }
Exemple #15
0
        private Transaction SignTransaction(Transaction tx)
        {
            if (tx == null)
            {
                Console.WriteLine($"no transaction specified");
                return(null);
            }
            SignatureContext context;

            try
            {
                context = new SignatureContext(tx);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine($"unsynchronized block");

                return(null);
            }

            current_wallet.Sign(context);

            if (context.Completed)
            {
                context.Verifiable.Scripts = context.GetScripts();
                current_wallet.SaveTransaction(tx);

                bool relay_result = local_node.Relay(tx);

                if (relay_result)
                {
                    return(tx);
                }
                else
                {
                    Console.WriteLine($"Local Node could not relay transaction: {tx.Hash.ToString()}");
                }
            }
            else
            {
                Console.WriteLine($"Incomplete Signature: {context.ToString()}");
            }

            return(null);
        }
Exemple #16
0
        public static void SignAndShowInformation(Transaction tx)
        {
            if (tx == null)
            {
                MessageBox.Show(Strings.InsufficientFunds);
                return;
            }
            if (tx.Attributes.All(p => p.Usage != TransactionAttributeUsage.Vote) && tx.Outputs.Any(p => p.AssetId.Equals(Blockchain.AntShare.Hash)) && Settings.Default.Votes.Count > 0)
            {
                tx.Attributes = tx.Attributes.Concat(Settings.Default.Votes.OfType <string>().Select(p => new TransactionAttribute
                {
                    Usage = TransactionAttributeUsage.Vote,
                    Data  = UInt256.Parse(p).ToArray()
                })).ToArray();
            }
            SignatureContext context;

            try
            {
                context = new SignatureContext(tx);
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show(Strings.UnsynchronizedBlock);
                return;
            }
            Program.CurrentWallet.Sign(context);
            if (context.Completed)
            {
                context.Signable.Scripts = context.GetScripts();
                Program.CurrentWallet.SaveTransaction(tx);
                Program.LocalNode.Relay(tx);
                InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle);
            }
            else
            {
                InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle);
            }
        }
        protected override JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "getbalance":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    UInt256            assetId = UInt256.Parse(_params[0].AsString());
                    IEnumerable <Coin> coins   = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(assetId));
                    JObject            json    = new JObject();
                    json["balance"]   = coins.Sum(p => p.Output.Value).ToString();
                    json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString();
                    return(json);
                }

            case "sendtoaddress":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UInt256 assetId    = UInt256.Parse(_params[0].AsString());
                    UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString());
                    Fixed8  value      = Fixed8.Parse(_params[2].AsString());
                    Fixed8  fee        = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero;
                    if (value <= Fixed8.Zero)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    ContractTransaction tx = Program.Wallet.MakeTransaction(new ContractTransaction
                    {
                        Outputs = new[]
                        {
                            new TransactionOutput
                            {
                                AssetId    = assetId,
                                Value      = value,
                                ScriptHash = scriptHash
                            }
                        }
                    }, fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    SignatureContext context = new SignatureContext(tx);
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Scripts = context.GetScripts();
                        Program.Wallet.SaveTransaction(tx);
                        LocalNode.Relay(tx);
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            default:
                return(base.Process(method, _params));
            }
        }
        protected override JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "getbalance":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    UInt256            assetId = UInt256.Parse(_params[0].AsString());
                    IEnumerable <Coin> coins   = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(assetId));
                    JObject            json    = new JObject();
                    json["balance"]   = coins.Sum(p => p.Output.Value).ToString();
                    json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString();
                    return(json);
                }

            case "sendtoaddress":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UInt256 assetId    = UInt256.Parse(_params[0].AsString());
                    UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString());
                    Fixed8  value      = Fixed8.Parse(_params[2].AsString());
                    if (value <= Fixed8.Zero)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero;
                    if (value < Fixed8.Zero)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    UInt160             change_address = _params.Count >= 5 ? Wallet.ToScriptHash(_params[4].AsString()) : null;
                    ContractTransaction tx             = Program.Wallet.MakeTransaction(new ContractTransaction
                    {
                        Outputs = new[]
                        {
                            new TransactionOutput
                            {
                                AssetId    = assetId,
                                Value      = value,
                                ScriptHash = scriptHash
                            }
                        }
                    }, change_address: change_address, fee: fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    SignatureContext context = new SignatureContext(tx);
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Scripts = context.GetScripts();
                        Program.Wallet.SaveTransaction(tx);
                        LocalNode.Relay(tx);
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "sendmany":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    JArray to = (JArray)_params[0];
                    if (to.Count == 0)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    TransactionOutput[] outputs = new TransactionOutput[to.Count];
                    for (int i = 0; i < to.Count; i++)
                    {
                        outputs[i] = new TransactionOutput
                        {
                            AssetId    = UInt256.Parse(to[i]["asset"].AsString()),
                            Value      = Fixed8.Parse(to[i]["value"].AsString()),
                            ScriptHash = Wallet.ToScriptHash(to[i]["address"].AsString())
                        };
                        if (outputs[i].Value <= Fixed8.Zero)
                        {
                            throw new RpcException(-32602, "Invalid params");
                        }
                    }
                    Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero;
                    if (fee < Fixed8.Zero)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    UInt160             change_address = _params.Count >= 3 ? Wallet.ToScriptHash(_params[2].AsString()) : null;
                    ContractTransaction tx             = Program.Wallet.MakeTransaction(new ContractTransaction
                    {
                        Outputs = outputs
                    }, change_address: change_address, fee: fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    SignatureContext context = new SignatureContext(tx);
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Scripts = context.GetScripts();
                        Program.Wallet.SaveTransaction(tx);
                        LocalNode.Relay(tx);
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "getnewaddress":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    KeyPair  key      = Program.Wallet.CreateKey();
                    Contract contract = Program.Wallet.GetContracts(key.PublicKeyHash).First(p => p.IsStandard);
                    return(contract.Address);
                }

            case "dumpprivkey":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UInt160 scriptHash = Wallet.ToScriptHash(_params[0].AsString());
                    KeyPair key        = Program.Wallet.GetKeyByScriptHash(scriptHash);
                    return(key.Export());
                }

            default:
                return(base.Process(method, _params));
            }
        }
Exemple #19
0
        private bool OnSendCommand(string[] args)
        {
            if (args.Length < 4 || args.Length > 5)
            {
                Console.WriteLine("error");
                return(true);
            }
            if (Program.Wallet == null)
            {
                Console.WriteLine("You have to open the wallet first.");
                return(true);
            }
            using (SecureString password = ReadSecureString("password"))
            {
                if (password.Length == 0)
                {
                    Console.WriteLine("cancelled");
                    return(true);
                }
                if (!Program.Wallet.VerifyPassword(password))
                {
                    Console.WriteLine("Incorrect password");
                    return(true);
                }
            }
            UInt256 assetId;

            switch (args[1].ToLower())
            {
            case "neo":
            case "ans":
                assetId = Blockchain.SystemShare.Hash;
                break;

            case "gas":
            case "anc":
                assetId = Blockchain.SystemCoin.Hash;
                break;

            default:
                assetId = UInt256.Parse(args[1]);
                break;
            }
            UInt160             scriptHash = Wallet.ToScriptHash(args[2]);
            bool                isSendAll  = string.Equals(args[3], "all", StringComparison.OrdinalIgnoreCase);
            ContractTransaction tx;

            if (isSendAll)
            {
                Coin[] coins = Program.Wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(assetId)).ToArray();
                tx = new ContractTransaction
                {
                    Attributes = new TransactionAttribute[0],
                    Inputs     = coins.Select(p => p.Reference).ToArray(),
                    Outputs    = new[]
                    {
                        new TransactionOutput
                        {
                            AssetId    = assetId,
                            Value      = coins.Sum(p => p.Output.Value),
                            ScriptHash = scriptHash
                        }
                    }
                };
            }
            else
            {
                if (!Fixed8.TryParse(args[3], out Fixed8 amount))
                {
                    Console.WriteLine("Incorrect Amount Format");
                    return(true);
                }
                if (amount.GetData() % (long)Math.Pow(10, 8 - Blockchain.Default.GetAssetState(assetId).Precision) != 0)
                {
                    Console.WriteLine("Incorrect Amount Precision");
                    return(true);
                }
                Fixed8 fee = args.Length >= 5 ? Fixed8.Parse(args[4]) : Fixed8.Zero;
                tx = Program.Wallet.MakeTransaction(new ContractTransaction
                {
                    Outputs = new[]
                    {
                        new TransactionOutput
                        {
                            AssetId    = assetId,
                            Value      = amount,
                            ScriptHash = scriptHash
                        }
                    }
                }, fee: fee);
                if (tx == null)
                {
                    Console.WriteLine("Insufficient funds");
                    return(true);
                }
            }
            SignatureContext context = new SignatureContext(tx);

            Program.Wallet.Sign(context);
            if (context.Completed)
            {
                tx.Scripts = context.GetScripts();
                Program.Wallet.SaveTransaction(tx);
                LocalNode.Relay(tx);
                Console.WriteLine($"TXID: {tx.Hash}");
            }
            else
            {
                Console.WriteLine("SignatureContext:");
                Console.WriteLine(context.ToString());
            }
            return(true);
        }
Exemple #20
0
        private JObject InternalCall(string method, JArray _params)
        {
            switch (method)
            {
            case "getbalance":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    UInt256            assetId = UInt256.Parse(_params[0].AsString());
                    IEnumerable <Coin> coins   = Program.Wallet.FindCoins().Where(p => p.AssetId.Equals(assetId));
                    JObject            json    = new JObject();
                    json["balance"]   = coins.Where(p => p.State == CoinState.Unspent || p.State == CoinState.Unconfirmed).Sum(p => p.Value).ToString();
                    json["confirmed"] = coins.Where(p => p.State == CoinState.Unspent).Sum(p => p.Value).ToString();
                    return(json);
                }

            case "getbestblockhash":
                return(Blockchain.Default.CurrentBlockHash.ToString());

            case "getblock":
            {
                Block block;
                if (_params[0] is JNumber)
                {
                    uint index = (uint)_params[0].AsNumber();
                    block = Blockchain.Default.GetBlock(index);
                }
                else
                {
                    UInt256 hash = UInt256.Parse(_params[0].AsString());
                    block = Blockchain.Default.GetBlock(hash);
                }
                if (block == null)
                {
                    throw new RpcException(-100, "Unknown block");
                }
                bool verbose = _params.Count >= 2 && _params[1].AsBooleanOrDefault(false);
                if (verbose)
                {
                    JObject json = block.ToJson();
                    json["confirmations"] = Blockchain.Default.Height - block.Height + 1;
                    UInt256 hash = Blockchain.Default.GetNextBlockHash(block.Hash);
                    if (hash != null)
                    {
                        json["nextblockhash"] = hash.ToString();
                    }
                    return(json);
                }
                else
                {
                    return(block.ToArray().ToHexString());
                }
            }

            case "getblockcount":
                return(Blockchain.Default.Height + 1);

            case "getblockhash":
            {
                uint height = (uint)_params[0].AsNumber();
                return(Blockchain.Default.GetBlockHash(height).ToString());
            }

            case "getconnectioncount":
                return(localNode.RemoteNodeCount);

            case "getrawmempool":
                return(new JArray(LocalNode.GetMemoryPool().Select(p => (JObject)p.Hash.ToString())));

            case "getrawtransaction":
            {
                UInt256     hash    = UInt256.Parse(_params[0].AsString());
                bool        verbose = _params.Count >= 2 && _params[1].AsBooleanOrDefault(false);
                int         height  = -1;
                Transaction tx      = LocalNode.GetTransaction(hash);
                if (tx == null)
                {
                    tx = Blockchain.Default.GetTransaction(hash, out height);
                }
                if (tx == null)
                {
                    throw new RpcException(-101, "Unknown transaction");
                }
                if (verbose)
                {
                    JObject json = tx.ToJson();
                    if (height >= 0)
                    {
                        Header header = Blockchain.Default.GetHeader((uint)height);
                        json["blockhash"]     = header.Hash.ToString();
                        json["confirmations"] = Blockchain.Default.Height - header.Height + 1;
                        json["blocktime"]     = header.Timestamp;
                    }
                    return(json);
                }
                else
                {
                    return(tx.ToArray().ToHexString());
                }
            }

            case "gettxout":
            {
                UInt256 hash  = UInt256.Parse(_params[0].AsString());
                ushort  index = (ushort)_params[1].AsNumber();
                return(Blockchain.Default.GetUnspent(hash, index)?.ToJson(index));
            }

            case "sendrawtransaction":
            {
                Transaction tx = Transaction.DeserializeFrom(_params[0].AsString().HexToBytes());
                return(localNode.Relay(tx));
            }

            case "sendtoaddress":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UInt256 assetId    = UInt256.Parse(_params[0].AsString());
                    UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString());
                    Fixed8  value      = Fixed8.Parse(_params[2].AsString());
                    Fixed8  fee        = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero;
                    if (value <= Fixed8.Zero)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    ContractTransaction tx = Program.Wallet.MakeTransaction(new ContractTransaction
                    {
                        Outputs = new[]
                        {
                            new TransactionOutput
                            {
                                AssetId    = assetId,
                                Value      = value,
                                ScriptHash = scriptHash
                            }
                        }
                    }, fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    SignatureContext context = new SignatureContext(tx);
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Scripts = context.GetScripts();
                        Program.Wallet.SaveTransaction(tx);
                        localNode.Relay(tx);
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "submitblock":
            {
                Block block = _params[0].AsString().HexToBytes().AsSerializable <Block>();
                return(localNode.Relay(block));
            }

            default:
                throw new RpcException(-32601, "Method not found");
            }
        }
        private bool OnSendCommand(string[] args)
        {
            if (Program.Wallet == null)
            {
                Console.WriteLine("You have to open the wallet first.");
                return(true);
            }
            if (args.Length < 4 || args.Length > 5)
            {
                Console.WriteLine("error");
                return(true);
            }
            UInt256 assetId;

            switch (args[1].ToLower())
            {
            case "ans":
                assetId = Blockchain.SystemShare.Hash;
                break;

            case "anc":
                assetId = Blockchain.SystemCoin.Hash;
                break;

            default:
                assetId = UInt256.Parse(args[1]);
                break;
            }
            UInt160 scriptHash = Wallet.ToScriptHash(args[2]);
            Fixed8  amount;

            if (!Fixed8.TryParse(args[3], out amount))
            {
                Console.WriteLine("Incorrect Amount Format");
                return(true);
            }
            if (amount.GetData() % (long)Math.Pow(10, 8 - Blockchain.Default.GetAssetState(assetId).Precision) != 0)
            {
                Console.WriteLine("Incorrect Amount Precision");
                return(true);
            }

            Fixed8 fee             = args.Length >= 5 ? Fixed8.Parse(args[4]) : Fixed8.Zero;
            ContractTransaction tx = Program.Wallet.MakeTransaction(new ContractTransaction
            {
                Outputs = new[]
                {
                    new TransactionOutput
                    {
                        AssetId    = assetId,
                        Value      = amount,
                        ScriptHash = scriptHash
                    }
                }
            }, fee: fee);

            if (tx == null)
            {
                Console.WriteLine("Insufficient funds");
                return(true);
            }
            using (SecureString password = ReadSecureString("password"))
            {
                if (password.Length == 0)
                {
                    Console.WriteLine("cancelled");
                    return(true);
                }
                if (!Program.Wallet.VerifyPassword(password))
                {
                    Console.WriteLine("Incorrect password");
                    return(true);
                }
            }
            SignatureContext context = new SignatureContext(tx);

            Program.Wallet.Sign(context);
            if (context.Completed)
            {
                tx.Scripts = context.GetScripts();
                Program.Wallet.SaveTransaction(tx);
                LocalNode.Relay(tx);
                Console.WriteLine($"TXID: {tx.Hash}");
            }
            else
            {
                Console.WriteLine("SignatureContext:");
                Console.WriteLine(context.ToString());
            }
            return(true);
        }