Example #1
0
        private void GetBalance(UInt160 assetHash, WalletAccount account)
        {
            try
            {
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    if (assetHash == Genesis.BcpContractAddress || assetHash == Genesis.BctContractAddress)
                    {
                        sb.EmitSysCall("Zoro.NativeNEP5.Call", "BalanceOf", assetHash, Account.ScriptHash);
                        sb.EmitSysCall("Zoro.NativeNEP5.Call", "Decimals", assetHash);
                        sb.EmitSysCall("Zoro.NativeNEP5.Call", "Symbol", assetHash);
                    }
                    else
                    {
                        sb.EmitAppCall(assetHash, "balanceOf", account.ScriptHash);
                        sb.EmitAppCall(assetHash, "decimals");
                        sb.EmitAppCall(assetHash, "symbol");
                    }

                    var script = sb.ToArray().ToHexString();
                    Zoro.IO.Json.JArray _params = new Zoro.IO.Json.JArray();
                    _params.Add("");
                    _params.Add(script);


                    Zoro.IO.Json.JObject info;
                    info = Program.Handler.Process("invokescript", _params);


                    JObject json = JObject.Parse(info.ToString());
                    string  decimals;
                    string  symbol  = "";
                    decimal balance = 0.00m;

                    if (json.ContainsKey("stack"))
                    {
                        JArray stack = json["stack"] as JArray;

                        symbol   = Encoding.UTF8.GetString(ZoroHelper.HexString2Bytes(stack[2]["value"].ToString()));
                        decimals = BigInteger.Parse(stack[1]["value"].ToString()).ToString();

                        if (stack[0]["value"].ToString() == "" || stack[1]["value"].ToString() == "" || stack[2]["value"].ToString() == "")
                        {
                            this.lblBalance.Text     = "0.00";
                            this.btnTransfer.Enabled = false;
                        }
                        else
                        {
                            string value = ZoroHelper.GetJsonValue((JObject)stack[0]);

                            balance = Math.Round(decimal.Parse(value) / (decimal)Math.Pow(10, double.Parse(decimals)), int.Parse(decimals));

                            if (balance != 0)
                            {
                                this.btnTransfer.Enabled = true;
                            }
                        }

                        Account     = account;
                        AssetHash   = assetHash;
                        AssetSymbol = symbol;
                        Decimals    = int.Parse(decimals);
                    }

                    this.lblAsset.Text   = assetHash.ToString() + "(" + symbol + ")";
                    this.lblBalance.Text = balance.ToString();
                }
            }
            catch
            {
                return;
            }
        }
Example #2
0
        public void FeeIsSignatureContract_TestScope_Global_Default()
        {
            // Global is supposed to be default

            Cosigner cosigner = new Cosigner();

            cosigner.Scopes.Should().Be(WitnessScope.Global);

            var wallet   = TestUtils.GenerateTestWallet();
            var snapshot = Blockchain.Singleton.GetSnapshot();

            // no password on this wallet
            using (var unlock = wallet.Unlock(""))
            {
                var acc = wallet.CreateAccount();

                // Fake balance

                var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash);

                var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState()));

                entry.GetInteroperable <Nep5AccountState>().Balance = 10000 * NativeContract.GAS.Factor;

                snapshot.Commit();

                // Make transaction
                // Manually creating script

                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    // self-transfer of 1e-8 GAS
                    System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value;
                    sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value);
                    sb.Emit(OpCode.ASSERT);
                    script = sb.ToArray();
                }

                // default to global scope
                var cosigners = new Cosigner[] { new Cosigner
                                                 {
                                                     Account = acc.ScriptHash
                                                 } };

                // using this...

                var tx = wallet.MakeTransaction(script, acc.ScriptHash, cosigners);

                Assert.IsNotNull(tx);
                Assert.IsNull(tx.Witnesses);

                // ----
                // Sign
                // ----

                var  data   = new ContractParametersContext(tx);
                bool signed = wallet.Sign(data);
                Assert.IsTrue(signed);

                // get witnesses from signed 'data'
                tx.Witnesses = data.GetWitnesses();
                tx.Witnesses.Length.Should().Be(1);

                // Fast check
                Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee));

                // Check
                long verificationGas = 0;
                foreach (var witness in tx.Witnesses)
                {
                    using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
                    {
                        engine.LoadScript(witness.VerificationScript);
                        engine.LoadScript(witness.InvocationScript);
                        Assert.AreEqual(VMState.HALT, engine.Execute());
                        Assert.AreEqual(1, engine.ResultStack.Count);
                        Assert.IsTrue(engine.ResultStack.Pop().ToBoolean());
                        verificationGas += engine.GasConsumed;
                    }
                }
                // get sizeGas
                var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot);
                // final check on sum: verification_cost + tx_size
                Assert.AreEqual(1264390, verificationGas + sizeGas);
                // final assert
                Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas);
            }
        }
Example #3
0
        public Transaction MakeTransaction(List <TransactionAttribute> attributes, IEnumerable <TransferOutput> outputs, UInt160 from = null, UInt160 fee_address = null, UInt160 change_address = null, Fixed8 fee = default(Fixed8))
        {
            var cOutputs = outputs.Where(p => !p.IsGlobalAsset).GroupBy(p => new
            {
                AssetId = (UInt160)p.AssetId,
                Account = p.ScriptHash
            }, (k, g) => new
            {
                k.AssetId,
                Value = g.Aggregate(BigInteger.Zero, (x, y) => x + y.Value.Value),
                k.Account
            }).ToArray();
            Transaction tx;

            if (attributes == null)
            {
                attributes = new List <TransactionAttribute>();
            }
            if (cOutputs.Length == 0)
            {
                tx = new ContractTransaction();
            }
            else
            {
                UInt160[]         accounts    = from == null?GetAccounts().Where(p => !p.Lock && !p.WatchOnly).Select(p => p.ScriptHash).ToArray() : new[] { from };
                HashSet <UInt160> sAttributes = new HashSet <UInt160>();
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    foreach (var output in cOutputs)
                    {
                        var balances = new List <(UInt160 Account, BigInteger Value)>();
                        foreach (UInt160 account in accounts)
                        {
                            byte[] script;
                            using (ScriptBuilder sb2 = new ScriptBuilder())
                            {
                                sb2.EmitAppCall(output.AssetId, "balanceOf", account);
                                script = sb2.ToArray();
                            }
                            ApplicationEngine engine = ApplicationEngine.Run(script);
                            if (engine.State.HasFlag(VMState.FAULT))
                            {
                                return(null);
                            }
                            balances.Add((account, engine.ResultStack.Pop().GetBigInteger()));
                        }
                        BigInteger sum = balances.Aggregate(BigInteger.Zero, (x, y) => x + y.Value);
                        if (sum < output.Value)
                        {
                            return(null);
                        }
                        if (sum != output.Value)
                        {
                            balances = balances.OrderByDescending(p => p.Value).ToList();
                            BigInteger amount = output.Value;
                            int        i      = 0;
                            while (balances[i].Value <= amount)
                            {
                                amount -= balances[i++].Value;
                            }
                            if (amount == BigInteger.Zero)
                            {
                                balances = balances.Take(i).ToList();
                            }
                            else
                            {
                                balances = balances.Take(i).Concat(new[] { balances.Last(p => p.Value >= amount) }).ToList();
                            }
                            sum = balances.Aggregate(BigInteger.Zero, (x, y) => x + y.Value);
                        }
                        sAttributes.UnionWith(balances.Select(p => p.Account));
                        for (int i = 0; i < balances.Count; i++)
                        {
                            BigInteger value = balances[i].Value;
                            if (i == 0)
                            {
                                BigInteger change = sum - output.Value;
                                if (change > 0)
                                {
                                    value -= change;
                                }
                            }
                            sb.EmitAppCall(output.AssetId, "transfer", balances[i].Account, output.Account, value);
                            sb.Emit(OpCode.THROWIFNOT);
                        }
                    }
                    byte[] nonce = new byte[8];
                    rand.NextBytes(nonce);
                    sb.Emit(OpCode.RET, nonce);
                    tx = new InvocationTransaction
                    {
                        Version = 1,
                        Script  = sb.ToArray()
                    };
                }
                attributes.AddRange(sAttributes.Select(p => new TransactionAttribute
                {
                    Usage = TransactionAttributeUsage.Script,
                    Data  = p.ToArray()
                }));
            }
            tx.Attributes = attributes.ToArray();
            tx.Inputs     = new CoinReference[0];
            tx.Outputs    = outputs.Where(p => p.IsGlobalAsset).Select(p => p.ToTxOutput()).ToArray();
            tx.Witnesses  = new Witness[0];
            if (tx is InvocationTransaction itx)
            {
                ApplicationEngine engine = ApplicationEngine.Run(itx.Script, itx);
                if (engine.State.HasFlag(VMState.FAULT))
                {
                    return(null);
                }
                tx = new InvocationTransaction
                {
                    Version    = itx.Version,
                    Script     = itx.Script,
                    Gas        = InvocationTransaction.GetGas(engine.GasConsumed),
                    Attributes = itx.Attributes,
                    Inputs     = itx.Inputs,
                    Outputs    = itx.Outputs
                };
            }
            tx = transactionContract.MakeTransaction(this, tx, from, fee_address, change_address, fee);//By BHP
            return(tx);
        }
Example #4
0
        async Task test_mintTokens()
        {
            decimal amount = 0;

            while (true)
            {
                subPrintLine("Input amount:");
                string str_amount = Console.ReadLine();
                try
                {
                    amount = decimal.Parse(str_amount);
                    break;
                }
                catch (Exception e)
                {
                    subPrintLine("input number");
                }
            }

            //获取地址的资产列表
            Dictionary <string, List <Utxo> > dir = await Helper.GetBalanceByAddress(Config.api, address);

            if (dir.ContainsKey(Config.id_GAS) == false)
            {
                subPrintLine("no gas");
                return;
            }
            Transaction tran = null;
            {
                byte[] script = null;
                using (var sb = new ScriptBuilder())
                {
                    var array = new MyJson.JsonNode_Array();
                    sb.EmitParamJson(array);                                              //参数倒序入
                    sb.EmitParamJson(new MyJson.JsonNode_ValueString("(str)mintTokens")); //参数倒序入
                    Hash160 shash = Config.dapp_sgas;
                    sb.EmitAppCall(shash);                                                //nep5脚本
                    script = sb.ToArray();
                }
                var sgasScripthash = Config.dapp_sgas;
                var targetaddr     = ThinNeo.Helper.GetAddressFromScriptHash(sgasScripthash);
                subPrintLine("contract address=" + targetaddr);//往合约地址转账

                //生成交易
                tran      = Helper.makeTran(dir[Config.id_GAS], targetaddr, new Hash256(Config.id_GAS), amount, (decimal)0.00000001);
                tran.type = TransactionType.InvocationTransaction;
                var idata = new InvokeTransData();
                tran.extdata = idata;
                idata.script = script;
                idata.gas    = (decimal)0.00000001;
                //sign and broadcast
                var signdata = ThinNeo.Helper.Sign(tran.GetMessage(), prikey);
                tran.AddWitness(signdata, pubkey, address);
                var    trandata    = tran.GetRawData();
                var    strtrandata = ThinNeo.Helper.Bytes2HexString(trandata);
                byte[] postdata;

                var a     = "d1012200c10a6d696e74546f6b656e7367be0da5478954f03c44c06d63bf613dc98c621e96010000000000000000011a47bddefb7d8fff356c939a1fed120d2848464f4ed719cf9134767a822dc936010002e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6000e1f50500000000be0da5478954f03c44c06d63bf613dc98c621e96e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c603e5dd190000000005ffb879d70015f9f8407eaad6adc3e196d8fbeac014140e6f9f97d589a6353f21ba25da7c1f430af10206d7a10597af22dc7d9c8aecef52338da3d1880a7edcc2178823fc7251ff3cb693e39da8da1c352eb3cc4f27045232103aa9038ee904c71cecf450c88a7ff0d23891d6cdc24b1eeb50bfd0e305fbec26bac";
                var aa    = ThinNeo.Helper.HexString2Bytes(a);
                var tran2 = new Transaction();
                tran2.Deserialize(new System.IO.MemoryStream(aa));

                var url    = Helper.MakeRpcUrlPost(Config.api, "sendrawtransaction", out postdata, new MyJson.JsonNode_ValueString(strtrandata));
                var result = await Helper.HttpPost(url, postdata);

                subPrintLine("得到的结果是:" + result);
                var json = MyJson.Parse(result).AsDict();
                if (json.ContainsKey("result"))
                {
                    var resultv = json["result"].AsList()[0].AsDict();
                    var txid    = resultv["txid"].AsString();
                    subPrintLine("txid=" + txid);
                }
            }
        }
Example #5
0
        public static async Task <string> api_SendbatchTransaction(byte[] prikey, Hash160 schash, string methodname, params string[] subparam)
        {
            byte[] pubkey  = ThinNeo.Helper.GetPublicKeyFromPrivateKey(prikey);
            string address = ThinNeo.Helper.GetAddressFromPublicKey(pubkey);

            byte[] data = null;
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                MyJson.JsonNode_Array array = new MyJson.JsonNode_Array();
                byte[] randombytes          = new byte[32];
                using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
                {
                    rng.GetBytes(randombytes);
                }
                BigInteger randomNum = new BigInteger(randombytes);
                sb.EmitPushNumber(randomNum);
                sb.Emit(ThinNeo.VM.OpCode.DROP);

                if (subparam != null && subparam.Length > 0)
                {
                    for (var i = 0; i < subparam.Length; i++)
                    {
                        array.AddArrayValue(subparam[i]);
                    }
                }
                sb.EmitParamJson(array);
                sb.EmitPushString(methodname);
                sb.EmitAppCall(schash);
                data = sb.ToArray();
            }
            //MakeTran
            ThinNeo.Transaction tran = new ThinNeo.Transaction();
            tran.version = 0;//0 or 1
            tran.inputs  = new ThinNeo.TransactionInput[0];
            tran.outputs = new ThinNeo.TransactionOutput[0];
            tran.type    = ThinNeo.TransactionType.InvocationTransaction;
            tran.extdata = new ThinNeo.InvokeTransData();
            var idata = new ThinNeo.InvokeTransData();

            tran.extdata = idata;
            idata.script = data;
            idata.gas    = 0;

            tran.attributes          = new ThinNeo.Attribute[1];
            tran.attributes[0]       = new ThinNeo.Attribute();
            tran.attributes[0].usage = ThinNeo.TransactionAttributeUsage.Script;
            tran.attributes[0].data  = ThinNeo.Helper.GetPublicKeyHashFromAddress(address);

            //sign and broadcast
            var signdata = ThinNeo.Helper.Sign(tran.GetMessage(), prikey);

            tran.AddWitness(signdata, pubkey, address);
            var trandata    = tran.GetRawData();
            var strtrandata = ThinNeo.Helper.Bytes2HexString(trandata);

            byte[] postdata;
            var    url    = Helper.MakeRpcUrlPost(Config.api, "sendrawtransaction", out postdata, new MyJson.JsonNode_ValueString(strtrandata));
            var    result = await Helper.HttpPost(url, postdata);

            return(result);
        }
Example #6
0
        private void timer1_Tick(object sender, EventArgs e)
        {
            uint walletHeight = 0;

            if (Program.CurrentWallet != null)
            {
                walletHeight = (Program.CurrentWallet.WalletHeight > 0) ? Program.CurrentWallet.WalletHeight - 1 : 0;
            }

            lbl_height.Text = $"{walletHeight}/{Blockchain.Singleton.Height}/{Blockchain.Singleton.HeaderHeight}";

            lbl_count_node.Text = LocalNode.Singleton.ConnectedCount.ToString();
            TimeSpan persistence_span = DateTime.UtcNow - persistence_time;

            if (persistence_span < TimeSpan.Zero)
            {
                persistence_span = TimeSpan.Zero;
            }
            if (persistence_span > Blockchain.TimePerBlock)
            {
                toolStripProgressBar1.Style = ProgressBarStyle.Marquee;
            }
            else
            {
                toolStripProgressBar1.Value = persistence_span.Seconds;
                toolStripProgressBar1.Style = ProgressBarStyle.Blocks;
            }
            if (Program.CurrentWallet != null)
            {
                if (Program.CurrentWallet.WalletHeight <= Blockchain.Singleton.Height + 1)
                {
                    if (balance_changed)
                    {
                        using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
                        {
                            IEnumerable <Coin> coins             = Program.CurrentWallet?.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent)) ?? Enumerable.Empty <Coin>();
                            Fixed8             bonus_available   = snapshot.CalculateBonus(Program.CurrentWallet.GetUnclaimedCoins().Select(p => p.Reference));
                            Fixed8             bonus_unavailable = snapshot.CalculateBonus(coins.Where(p => p.State.HasFlag(CoinState.Confirmed) && p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).Select(p => p.Reference), snapshot.Height + 1);
                            Fixed8             bonus             = bonus_available + bonus_unavailable;
                            var assets = coins.GroupBy(p => p.Output.AssetId, (k, g) => new
                            {
                                Asset = snapshot.Assets.TryGet(k),
                                Value = g.Sum(p => p.Output.Value),
                                Claim = k.Equals(Blockchain.UtilityToken.Hash) ? bonus : Fixed8.Zero
                            }).ToDictionary(p => p.Asset.AssetId);
                            if (bonus != Fixed8.Zero && !assets.ContainsKey(Blockchain.UtilityToken.Hash))
                            {
                                assets[Blockchain.UtilityToken.Hash] = new
                                {
                                    Asset = snapshot.Assets.TryGet(Blockchain.UtilityToken.Hash),
                                    Value = Fixed8.Zero,
                                    Claim = bonus
                                };
                            }
                            var balance_ans = coins.Where(p => p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).GroupBy(p => p.Output.ScriptHash).ToDictionary(p => p.Key, p => p.Sum(i => i.Output.Value));
                            var balance_anc = coins.Where(p => p.Output.AssetId.Equals(Blockchain.UtilityToken.Hash)).GroupBy(p => p.Output.ScriptHash).ToDictionary(p => p.Key, p => p.Sum(i => i.Output.Value));
                            foreach (ListViewItem item in listView1.Items)
                            {
                                UInt160 script_hash = item.Name.ToScriptHash();
                                Fixed8  ans         = balance_ans.ContainsKey(script_hash) ? balance_ans[script_hash] : Fixed8.Zero;
                                Fixed8  anc         = balance_anc.ContainsKey(script_hash) ? balance_anc[script_hash] : Fixed8.Zero;
                                item.SubItems["ans"].Text = ans.ToString();
                                item.SubItems["anc"].Text = anc.ToString();
                            }
                            foreach (AssetState asset in listView2.Items.OfType <ListViewItem>().Select(p => p.Tag as AssetState).Where(p => p != null).ToArray())
                            {
                                if (!assets.ContainsKey(asset.AssetId))
                                {
                                    listView2.Items.RemoveByKey(asset.AssetId.ToString());
                                }
                            }
                            foreach (var asset in assets.Values)
                            {
                                string value_text = asset.Value.ToString() + (asset.Asset.AssetId.Equals(Blockchain.UtilityToken.Hash) ? $"+({asset.Claim})" : "");
                                if (listView2.Items.ContainsKey(asset.Asset.AssetId.ToString()))
                                {
                                    listView2.Items[asset.Asset.AssetId.ToString()].SubItems["value"].Text = value_text;
                                }
                                else
                                {
                                    string asset_name = asset.Asset.AssetType == AssetType.GoverningToken ? "OXS" :
                                                        asset.Asset.AssetType == AssetType.UtilityToken ? "OXC" :
                                                        asset.Asset.GetName();
                                    listView2.Items.Add(new ListViewItem(new[]
                                    {
                                        new ListViewItem.ListViewSubItem
                                        {
                                            Name = "name",
                                            Text = asset_name
                                        },
                                        new ListViewItem.ListViewSubItem
                                        {
                                            Name = "type",
                                            Text = asset.Asset.AssetType.ToString()
                                        },
                                        new ListViewItem.ListViewSubItem
                                        {
                                            Name = "value",
                                            Text = value_text
                                        },
                                        new ListViewItem.ListViewSubItem
                                        {
                                            ForeColor = Color.Gray,
                                            Name      = "issuer",
                                            Text      = $"{LanHelper.LocalLanguage("unknown issuer")}[{asset.Asset.Owner}]"
                                        }
                                    }, -1, listView2.Groups["unchecked"])
                                    {
                                        Name = asset.Asset.AssetId.ToString(),
                                        Tag  = asset.Asset,
                                        UseItemStyleForSubItems = false
                                    });
                                }
                            }
                            balance_changed = false;
                        }
                    }
                    foreach (ListViewItem item in listView2.Groups["unchecked"].Items.OfType <ListViewItem>().ToArray())
                    {
                        ListViewItem.ListViewSubItem subitem = item.SubItems["issuer"];
                        AssetState             asset         = (AssetState)item.Tag;
                        CertificateQueryResult result;
                        if (asset.AssetType == AssetType.GoverningToken || asset.AssetType == AssetType.UtilityToken)
                        {
                            result = new CertificateQueryResult {
                                Type = CertificateQueryResultType.System
                            };
                        }
                        else
                        {
                            result = CertificateQueryService.Query(asset.Owner);
                        }
                        using (result)
                        {
                            subitem.Tag = result.Type;
                            switch (result.Type)
                            {
                            case CertificateQueryResultType.Querying:
                            case CertificateQueryResultType.QueryFailed:
                                break;

                            case CertificateQueryResultType.System:
                                subitem.ForeColor = Color.Green;
                                subitem.Text      = LanHelper.LocalLanguage("OX system");
                                break;

                            case CertificateQueryResultType.Invalid:
                                subitem.ForeColor = Color.Red;
                                subitem.Text      = $"[{ LanHelper.LocalLanguage("Invalid")}][{asset.Owner}]";
                                break;

                            case CertificateQueryResultType.Expired:
                                subitem.ForeColor = Color.Yellow;
                                subitem.Text      = $"[{LanHelper.LocalLanguage("Expired")}]{result.Certificate.Subject}[{asset.Owner}]";
                                break;

                            case CertificateQueryResultType.Good:
                                subitem.ForeColor = Color.Black;
                                subitem.Text      = $"{result.Certificate.Subject}[{asset.Owner}]";
                                break;
                            }
                            switch (result.Type)
                            {
                            case CertificateQueryResultType.System:
                            case CertificateQueryResultType.Missing:
                            case CertificateQueryResultType.Invalid:
                            case CertificateQueryResultType.Expired:
                            case CertificateQueryResultType.Good:
                                item.Group = listView2.Groups["checked"];
                                break;
                            }
                        }
                    }
                }
                if (check_nep5_balance && persistence_span > TimeSpan.FromSeconds(2))
                {
                    UInt160[] addresses = Program.CurrentWallet.GetAccounts().Select(p => p.ScriptHash).ToArray();
                    foreach (string s in Settings.Default.NEP5Watched)
                    {
                        UInt160 script_hash = UInt160.Parse(s);
                        byte[]  script;
                        using (ScriptBuilder sb = new ScriptBuilder())
                        {
                            foreach (UInt160 address in addresses)
                            {
                                sb.EmitAppCall(script_hash, "balanceOf", address);
                            }
                            sb.Emit(OpCode.DEPTH, OpCode.PACK);
                            sb.EmitAppCall(script_hash, "decimals");
                            sb.EmitAppCall(script_hash, "name");
                            script = sb.ToArray();
                        }
                        ApplicationEngine engine = ApplicationEngine.Run(script);
                        if (engine.State.HasFlag(VMState.FAULT))
                        {
                            continue;
                        }
                        string     name     = engine.ResultStack.Pop().GetString();
                        byte       decimals = (byte)engine.ResultStack.Pop().GetBigInteger();
                        BigInteger amount   = ((VMArray)engine.ResultStack.Pop()).Aggregate(BigInteger.Zero, (x, y) => x + y.GetBigInteger());
                        if (amount == 0)
                        {
                            listView2.Items.RemoveByKey(script_hash.ToString());
                            continue;
                        }
                        BigDecimal balance    = new BigDecimal(amount, decimals);
                        string     value_text = balance.ToString();
                        if (listView2.Items.ContainsKey(script_hash.ToString()))
                        {
                            listView2.Items[script_hash.ToString()].SubItems["value"].Text = value_text;
                        }
                        else
                        {
                            listView2.Items.Add(new ListViewItem(new[]
                            {
                                new ListViewItem.ListViewSubItem
                                {
                                    Name = "name",
                                    Text = name
                                },
                                new ListViewItem.ListViewSubItem
                                {
                                    Name = "type",
                                    Text = "NEP-5"
                                },
                                new ListViewItem.ListViewSubItem
                                {
                                    Name = "value",
                                    Text = value_text
                                },
                                new ListViewItem.ListViewSubItem
                                {
                                    ForeColor = Color.Gray,
                                    Name      = "issuer",
                                    Text      = $"ScriptHash:{script_hash}"
                                }
                            }, -1, listView2.Groups["checked"])
                            {
                                Name = script_hash.ToString(),
                                UseItemStyleForSubItems = false
                            });
                        }
                    }
                    check_nep5_balance = false;
                }
            }
        }
Example #7
0
        public void Runtime_GetNotifications_Test()
        {
            UInt160 scriptHash2;
            var     snapshot = Blockchain.Singleton.GetSnapshot();

            using (var script = new ScriptBuilder())
            {
                // Drop arguments

                script.Emit(OpCode.NIP);

                // Notify method

                script.EmitSysCall(InteropService.Runtime.Notify);

                // Add return

                script.EmitPush(true);

                // Mock contract

                scriptHash2 = script.ToArray().ToScriptHash();

                snapshot.Contracts.Delete(scriptHash2);
                snapshot.Contracts.Add(scriptHash2, new Neo.Ledger.ContractState()
                {
                    Script   = script.ToArray(),
                    Manifest = ContractManifest.CreateDefault(scriptHash2),
                });
            }

            // Wrong length

            using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
                using (var script = new ScriptBuilder())
                {
                    // Retrive

                    script.EmitPush(1);
                    script.EmitSysCall(InteropService.Runtime.GetNotifications);

                    // Execute

                    engine.LoadScript(script.ToArray());

                    Assert.AreEqual(VMState.FAULT, engine.Execute());
                }

            // All test

            using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
                using (var script = new ScriptBuilder())
                {
                    // Notification 1 -> 13

                    script.EmitPush(13);
                    script.EmitSysCall(InteropService.Runtime.Notify);

                    // Call script

                    script.EmitAppCall(scriptHash2, "test");

                    // Drop return

                    script.Emit(OpCode.DROP);

                    // Receive all notifications

                    script.Emit(OpCode.PUSHNULL);
                    script.EmitSysCall(InteropService.Runtime.GetNotifications);

                    // Execute

                    engine.LoadScript(script.ToArray());
                    var currentScriptHash = engine.EntryScriptHash;

                    Assert.AreEqual(VMState.HALT, engine.Execute());
                    Assert.AreEqual(1, engine.ResultStack.Count);
                    Assert.AreEqual(2, engine.Notifications.Count);

                    Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(VM.Types.Array));

                    var array = (VM.Types.Array)engine.ResultStack.Pop();

                    // Check syscall result

                    AssertNotification(array[1], scriptHash2, "test");
                    AssertNotification(array[0], currentScriptHash, 13);

                    // Check notifications

                    Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash);
                    Assert.AreEqual("test", engine.Notifications[1].State.GetString());

                    Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash);
                    Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger());
                }

            // Script notifications

            using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
                using (var script = new ScriptBuilder())
                {
                    // Notification 1 -> 13

                    script.EmitPush(13);
                    script.EmitSysCall(InteropService.Runtime.Notify);

                    // Call script

                    script.EmitAppCall(scriptHash2, "test");

                    // Drop return

                    script.Emit(OpCode.DROP);

                    // Receive all notifications

                    script.EmitPush(scriptHash2.ToArray());
                    script.EmitSysCall(InteropService.Runtime.GetNotifications);

                    // Execute

                    engine.LoadScript(script.ToArray());
                    var currentScriptHash = engine.EntryScriptHash;

                    Assert.AreEqual(VMState.HALT, engine.Execute());
                    Assert.AreEqual(1, engine.ResultStack.Count);
                    Assert.AreEqual(2, engine.Notifications.Count);

                    Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(VM.Types.Array));

                    var array = (VM.Types.Array)engine.ResultStack.Pop();

                    // Check syscall result

                    AssertNotification(array[0], scriptHash2, "test");

                    // Check notifications

                    Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash);
                    Assert.AreEqual("test", engine.Notifications[1].State.GetString());

                    Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash);
                    Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger());
                }

            // Clean storage

            snapshot.Contracts.Delete(scriptHash2);
        }
Example #8
0
        /// <summary>
        /// apply for new validator
        /// </summary>
        /// <param name="pubkey"></param>
        /// <returns></returns>
        public async Task <object> ApplyForValidator(string pubkey)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (pubkey.IsNull())
            {
                return(Error(ErrorCode.ParameterIsNull));
            }
            ECPoint publicKey = null;

            try
            {
                publicKey = ECPoint.Parse(pubkey, ECCurve.Secp256r1);
            }
            catch (Exception e)
            {
                return(Error(ErrorCode.InvalidPara));
            }
            using var snapshot = Blockchain.Singleton.GetSnapshot();
            var validators = NativeContract.NEO.GetRegisteredValidators(snapshot);

            if (validators.Any(v => v.PublicKey.ToString() == pubkey))
            {
                return(Error(ErrorCode.ValidatorAlreadyExist));
            }
            VerificationContract contract = new VerificationContract
            {
                Script        = SmartContract.Contract.CreateSignatureRedeemScript(publicKey),
                ParameterList = new[] { ContractParameterType.Signature }
            };

            var account = contract.ScriptHash;

            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitAppCall(NativeContract.NEO.Hash, "registerValidator", publicKey);

            Transaction tx = null;

            try
            {
                tx = CurrentWallet.InitTransaction(sb.ToArray(), account);
            }
            catch (InvalidOperationException)
            {
                return(Error(ErrorCode.EngineFault));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
            if (!signSuccess)
            {
                return(Error(ErrorCode.SignFail, context.SafeSerialize()));
            }
            var result = new VoteResultModel();
            await tx.Broadcast();

            result.TxId = tx.Hash;
            return(result);
        }
Example #9
0
        /// <summary>
        /// vote for consensus node
        /// </summary>
        /// <returns></returns>
        public async Task <object> VoteCN(UInt160 account, string[] pubkeys)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (account == null || pubkeys.IsEmpty())
            {
                return(Error(ErrorCode.ParameterIsNull));
            }
            ECPoint[] publicKeys = null;
            try
            {
                publicKeys = pubkeys.Select(p => ECPoint.Parse(p, ECCurve.Secp256r1)).ToArray();
            }
            catch (Exception e)
            {
                return(Error(ErrorCode.InvalidPara));
            }
            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitAppCall(NativeContract.NEO.Hash, "vote", new ContractParameter
            {
                Type  = ContractParameterType.Hash160,
                Value = account
            }, new ContractParameter
            {
                Type  = ContractParameterType.Array,
                Value = publicKeys.Select(p => new ContractParameter
                {
                    Type  = ContractParameterType.PublicKey,
                    Value = p
                }).ToArray()
            });

            Transaction tx = null;

            try
            {
                tx = CurrentWallet.InitTransaction(sb.ToArray(), account);
            }
            catch (InvalidOperationException)
            {
                return(Error(ErrorCode.EngineFault));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
            if (!signSuccess)
            {
                return(Error(ErrorCode.SignFail, context.SafeSerialize()));
            }
            var result = new VoteResultModel();
            await tx.Broadcast();

            result.TxId = tx.Hash;
            return(result);
        }
Example #10
0
        private Transaction GenerateTransaction()
        {
            var cOutputs = this.Items.Where(p => p.AssetId is UInt160).GroupBy(p => new
            {
                AssetId = (UInt160)p.AssetId,
                Account = p.ScriptHash
            }, (k, g) => new
            {
                AssetId = k.AssetId,
                Value   = g.Aggregate(BigInteger.Zero, (x, y) => x + y.Value.Value),
                Account = k.Account
            }).ToArray();
            Transaction tx;
            var         attributes = new List <TransactionAttribute>();

            if (cOutputs.Length == 0)
            {
                tx = new ContractTransaction();
            }
            else
            {
                var addresses   = this.walletController.GetAccounts().Select(p => p.ScriptHash).ToArray();
                var sAttributes = new HashSet <UInt160>();
                using (var builder = new ScriptBuilder())
                {
                    foreach (var output in cOutputs)
                    {
                        byte[] script;
                        using (var builder2 = new ScriptBuilder())
                        {
                            foreach (var address in addresses)
                            {
                                builder2.EmitAppCall(output.AssetId, "balanceOf", address);
                            }

                            builder2.Emit(OpCode.DEPTH, OpCode.PACK);
                            script = builder2.ToArray();
                        }

                        var engine = ApplicationEngine.Run(script);
                        if (engine.State.HasFlag(VMState.FAULT))
                        {
                            return(null);
                        }

                        var balances = engine.EvaluationStack.Pop().GetArray().Reverse().Zip(addresses, (i, a) => new
                        {
                            Account = a,
                            Value   = i.GetBigInteger()
                        }).ToArray();

                        var sum = balances.Aggregate(BigInteger.Zero, (x, y) => x + y.Value);
                        if (sum < output.Value)
                        {
                            return(null);
                        }

                        if (sum != output.Value)
                        {
                            balances = balances.OrderByDescending(p => p.Value).ToArray();
                            var amount = output.Value;
                            var i      = 0;
                            while (balances[i].Value <= amount)
                            {
                                amount -= balances[i++].Value;
                            }

                            balances = amount == BigInteger.Zero
                                ? balances.Take(i).ToArray()
                                : balances.Take(i).Concat(new[] { balances.Last(p => p.Value >= amount) }).ToArray();

                            sum = balances.Aggregate(BigInteger.Zero, (x, y) => x + y.Value);
                        }

                        sAttributes.UnionWith(balances.Select(p => p.Account));

                        for (int i = 0; i < balances.Length; i++)
                        {
                            var value = balances[i].Value;
                            if (i == 0)
                            {
                                var change = sum - output.Value;
                                if (change > 0)
                                {
                                    value -= change;
                                }
                            }
                            builder.EmitAppCall(output.AssetId, "transfer", balances[i].Account, output.Account, value);
                            builder.Emit(OpCode.THROWIFNOT);
                        }
                    }

                    tx = new InvocationTransaction
                    {
                        Version = 1,
                        Script  = builder.ToArray()
                    };
                }
                attributes.AddRange(sAttributes.Select(p => new TransactionAttribute
                {
                    Usage = TransactionAttributeUsage.Script,
                    Data  = p.ToArray()
                }));
            }

            if (!string.IsNullOrEmpty(remark))
            {
                attributes.Add(new TransactionAttribute
                {
                    Usage = TransactionAttributeUsage.Remark,
                    Data  = Encoding.UTF8.GetBytes(remark)
                });
            }

            tx.Attributes = attributes.ToArray();
            tx.Outputs    = this.Items.Where(p => p.AssetId is UInt256).Select(p => p.ToTxOutput()).ToArray();

            if (tx is ContractTransaction ctx)
            {
                tx = this.walletController.MakeTransaction(ctx);
            }

            return(tx);
        }
Example #11
0
        public async Task <object> InvokeContract(InvokeContractParameterModel para)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (para.ContractHash == null || para.Method.IsNull())
            {
                return(Error(ErrorCode.ParameterIsNull));
            }
            using var snapshot = Blockchain.Singleton.GetSnapshot();
            var contract = snapshot.Contracts.TryGet(para.ContractHash);

            if (contract == null)
            {
                return(Error(ErrorCode.UnknownContract));
            }
            ContractParameter[] contractParameters = para.Parameters?.Select(p =>
            {
                var parameterValue = new ContractParameter(p.Type);
                parameterValue.SetValue(p.Value);
                return(parameterValue);
            }).ToArray();

            var signers = new List <Cosigner>();

            if (para.Cosigners.NotEmpty())
            {
                signers.AddRange(para.Cosigners.Select(s => new Cosigner()
                {
                    Account = s.Account, Scopes = s.Scopes
                }));
            }

            Transaction tx = null;

            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitAppCall(para.ContractHash, para.Method, contractParameters);

            try
            {
                tx = CurrentWallet.InitTransaction(sb.ToArray(), signers.ToArray());
            }
            catch (InvalidOperationException)
            {
                return(Error(ErrorCode.EngineFault));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
            if (!signSuccess)
            {
                return(Error(ErrorCode.SignFail, context.SafeSerialize()));
            }
            var result = new InvokeResultModel();

            using ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx, testMode: true);
            result.VmState     = engine.State;
            result.GasConsumed = new BigDecimal(tx.SystemFee, NativeContract.GAS.Decimals);
            result.ResultStack = engine.ResultStack.Select(p => JStackItem.FromJson(p.ToParameter().ToJson())).ToList();
            if (engine.State.HasFlag(VMState.FAULT))
            {
                return(Error(ErrorCode.EngineFault));
            }
            if (!para.SendTx)
            {
                return(result);
            }
            await tx.Broadcast();

            result.TxId = tx.Hash;
            return(result);
        }
Example #12
0
        public async Task <JObject> sendTransaction(byte[] prikey, Hash160 schash, string method, string[] subparam)
        {
            // 构造合约交易
            byte[] data = null;
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                MyJson.JsonNode_Array array = new MyJson.JsonNode_Array();

                //
                byte[] randombytes = new byte[32];
                using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
                {
                    rng.GetBytes(randombytes);
                }
                BigInteger randomNum = new BigInteger(randombytes);
                sb.EmitPushNumber(randomNum);
                sb.Emit(ThinNeo.VM.OpCode.DROP);

                for (var i = 0; i < subparam.Length; i++)
                {
                    array.AddArrayValue(subparam[i]);
                }
                sb.EmitParamJson(array);
                sb.EmitPushString(method);
                sb.EmitAppCall(schash);
                data = sb.ToArray();
            }

            // 获取余额
            //string id_nnc = assetid;
            Dictionary <string, List <Utxo> > dir = getBalance(accountInfo.address);

            if (dir == null || dir[id_gas] == null)
            {
                // 余额不足
                return(insufficientBalance());
            }

            // 构造并签名
            var tran = new ThinNeo.Transaction();

            tran.type    = ThinNeo.TransactionType.InvocationTransaction;
            tran.extdata = new ThinNeo.InvokeTransData {
                script = data, gas = 0
            };
            tran.inputs              = new ThinNeo.TransactionInput[0];
            tran.outputs             = new ThinNeo.TransactionOutput[0];
            tran.attributes          = new ThinNeo.Attribute[1];
            tran.attributes[0]       = new ThinNeo.Attribute();
            tran.attributes[0].usage = TransactionAttributeUsage.Script;
            tran.attributes[0].data  = ThinNeo.Helper.GetPublicKeyHashFromAddress(accountInfo.address);

            byte[] signdata = ThinNeo.Helper.Sign(tran.GetMessage(), prikey);
            tran.AddWitness(signdata, accountInfo.pubkey, accountInfo.address);
            string txid = tran.GetHash().ToString();

            byte[] transdata = tran.GetRawData();
            string rawdata   = ThinNeo.Helper.Bytes2HexString(transdata);

            // 发送交易
            try
            {
                byte[] postdata;
                string url    = TransHelper.MakeRpcUrlPost(nelJsonRpcUrl, "sendrawtransaction", out postdata, new MyJson.JsonNode_ValueString(rawdata));
                var    result = await TransHelper.HttpPost(url, postdata);

                Console.WriteLine("result:" + result);
                if (JObject.Parse(result)["result"] == null)
                {
                    return(txFail(txid));
                }
                JObject res  = (JObject)(((JArray)(JObject.Parse(result)["result"]))[0]);
                string  flag = res["sendrawtransactionresult"].ToString();
                if (flag.ToLower() != "true" && res["txid"].ToString() != txid)
                {
                    return(txFail(txid));
                }
                return(txSucc(txid));
            }
            catch (Exception)
            {
                return(txFail(txid));
            }
        }
Example #13
0
        internal static bool VerifyScripts(this IVerifiable verifiable)
        {
            bool   bLog    = false;
            string logpath = "";

            if (verifiable is Transaction)
            {
                var hash = (verifiable as Transaction).Hash;
                if (Neo.SmartContract.Debug.FullLog.TestNeedLog(hash))
                {
                    bLog    = true;
                    logpath = System.IO.Path.Combine(Neo.SmartContract.Debug.FullLog.Path, hash.ToString());
                }
            }

            UInt160[] hashes;
            try
            {
                hashes = verifiable.GetScriptHashesForVerifying();
            }
            catch (InvalidOperationException)
            {
                return(false);
            }
            if (hashes.Length != verifiable.Scripts.Length)
            {
                return(false);
            }
            for (int i = 0; i < hashes.Length; i++)
            {
                byte[] verification = verifiable.Scripts[i].VerificationScript;
                if (verification.Length == 0)
                {
                    using (ScriptBuilder sb = new ScriptBuilder())
                    {
                        sb.EmitAppCall(hashes[i].ToArray());
                        verification = sb.ToArray();
                    }
                }
                else
                {
                    if (hashes[i] != verifiable.Scripts[i].ScriptHash)
                    {
                        return(false);
                    }
                }
                using (StateReader service = new StateReader())
                {
                    ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, verifiable, Blockchain.Default, service, Fixed8.Zero);
                    if (bLog)
                    {
                        engine.BeginDebug();
                    }
                    engine.LoadScript(verification, false);
                    engine.LoadScript(verifiable.Scripts[i].InvocationScript, true);
                    if (!engine.Execute())
                    {
                        return(false);
                    }
                    if (bLog)
                    {
                        string filename = logpath + "[" + i + "].llvmhex.txt";
                        if (engine.FullLog != null)
                        {
                            engine.FullLog.Save(filename);
                        }
                    }
                    if (engine.EvaluationStack.Count != 1 || !engine.EvaluationStack.Pop().GetBoolean())
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Example #14
0
        /// <summary>
        /// Transfer NEP5 tokens.
        /// </summary>
        /// <param name="attributes"></param>
        /// <param name="outputs"></param>
        /// <param name="changeAddress"></param>
        /// <param name="fee"></param>
        /// <returns></returns>
        public override async Task <Transaction> TransferNep5(List <TransactionAttribute> attributes,
                                                              IEnumerable <TransferOutput> outputs,
                                                              UInt160 changeAddress = null, decimal fee = 0)
        {
            InvocationTransaction tx;
            var cOutputs = outputs.Where(p => !p.IsGlobalAsset).GroupBy(p => new
            {
                AssetId = (UInt160)p.AssetId,
                Account = p.ScriptHash
            }, (k, g) => new
            {
                k.AssetId,
                Value = g.Aggregate(BigInteger.Zero, (x, y) => x + y.Value.Value),
                k.Account
            }).ToArray();

            if (cOutputs.Length == 0)
            {
                return(null);
            }
            var nep5Balances = await TransactionBuilderHelper.GetNep5Balances(AddressScriptHash.ToAddress(), _restService);

            using (ScriptBuilder sb = new ScriptBuilder())
            {
                foreach (var output in cOutputs)
                {
                    var nep5Balance = nep5Balances.SingleOrDefault(x => x.AssetHash == output.AssetId.ToString().Remove(0, 2));
                    if (nep5Balance == null)
                    {
                        throw new WalletException($"Not enough balance of: {output.AssetId} ");
                    }
                    sb.EmitAppCall(output.AssetId, Nep5Methods.transfer.ToString(), AddressScriptHash, output.Account, output.Value);
                    sb.Emit(OpCode.THROWIFNOT);
                }

                byte[] nonce = GenerateNonce(8);
                sb.Emit(OpCode.RET, nonce);
                tx = new InvocationTransaction
                {
                    Version = 1,
                    Script  = sb.ToArray()
                };
            }

            if (attributes == null)
            {
                attributes = new List <TransactionAttribute>();
            }
            attributes.Add(new TransactionAttribute
            {
                Usage = TransactionAttributeUsage.Script,
                Data  = AddressScriptHash.ToArray()
            });

            tx.Attributes = attributes.ToArray();
            tx.Inputs     = new CoinReference[0];
            tx.Outputs    = outputs.Where(p => p.IsGlobalAsset).Select(p => p.ToTxOutput()).ToArray();
            tx.Witnesses  = new Witness[0];

            var gasConsumed = await EstimateGasAsync(tx.Script.ToHexString()); //todo add gas limit

            tx.Gas = InvocationTransaction.GetGas(Fixed8.FromDecimal(gasConsumed));

            tx = MakeTransaction(tx, AddressScriptHash, changeAddress, Fixed8.FromDecimal(fee));
            var success = await SignAndSendTransaction(tx);

            return(success ? tx : null);
        }
Example #15
0
        //Transfer NEP-5 Asset
        public static Transaction CreateNep5Transfer(SignDelegate sign)
        {
            var from    = "AS8UDW7aLhrywLVHFL3ny5tSBaVhWTeZjT".ToScriptHash();
            var assetId = new UInt160("ceab719b8baa2310f232ee0d277c061704541cfb".HexToBytes().Reverse().ToArray());
            var to      = "AS8UDW7aLhrywLVHFL3ny5tSBaVhWTeZjT".ToScriptHash();
            var value   = 100;

            //交易输入是 1 GAS
            var inputs = new List <CoinReference> {
                //coin reference A
                new CoinReference()
                {
                    PrevHash  = new UInt256("0x51ac4f7f1662d8c9379ccce3fa7cd2085b9a865edfa53ad892352a41768dd1de".Remove(0, 2).HexToBytes().Reverse().ToArray()),
                    PrevIndex = 0
                }
            }.ToArray();
            //交易输出是 0.999 GAS,找回到原地址
            var outputs = new List <TransactionOutput> {
                new TransactionOutput()
                {
                    AssetId    = Blockchain.UtilityToken.Hash,                        //Asset Id, this is NEO
                    ScriptHash = "AJd31a8rYPEBkY1QSxpsGy8mdU4vTYTD4U".ToScriptHash(), //Receiver
                    Value      = new Fixed8((long)(0.999 * (long)Math.Pow(10, 8)))    //Value (satoshi unit)
                }
            }.ToArray();

            //则手续费是 0.001 GAS

            //Query Balances
            using (ScriptBuilder sb2 = new ScriptBuilder())
            {
                byte[] script;
                sb2.EmitAppCall(assetId, "balanceOf", from);
                sb2.Emit(OpCode.DEPTH, OpCode.PACK);
                script = sb2.ToArray();
                ApplicationEngine engine = ApplicationEngine.Run(script);
                if (engine.State.HasFlag(VMState.FAULT))
                {
                    return(null);
                }
                var        balances = ((VMArray)engine.ResultStack.Pop())[0];
                BigInteger sum      = balances.GetBigInteger();
                if (sum < value)
                {
                    Console.WriteLine("Insufficient balance");
                    return(null);
                }
            }

            //Transfer
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitAppCall(assetId, "transfer", from, to, value);
                sb.Emit(OpCode.THROWIFNOT);

                byte[] nonce = new byte[8];
                Random rand  = new Random();
                rand.NextBytes(nonce);
                sb.Emit(OpCode.RET, nonce);
                var tx = new InvocationTransaction
                {
                    Version    = 1,
                    Script     = sb.ToArray(),
                    Outputs    = outputs,
                    Inputs     = inputs,
                    Attributes = new TransactionAttribute[0],
                    Witnesses  = new Witness[0]
                };
                return(sign.Invoke(tx));
            }
        }
Example #16
0
        Result.GetVarSize();                //Result

        static OracleResponse()
        {
            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitAppCall(NativeContract.Oracle.Hash, "finish");
            FixedScript = sb.ToArray();
        }
Example #17
0
        public void OnPersist(Snapshot snapshot, IReadOnlyList <Blockchain.ApplicationExecuted> applicationExecutedList)
        {
            // Start freshly with a new DBCache for each block.
            ResetBatch();
            Dictionary <Nep5BalanceKey, Nep5Balance> nep5BalancesChanged = new Dictionary <Nep5BalanceKey, Nep5Balance>();

            ushort transferIndex = 0;

            foreach (Blockchain.ApplicationExecuted appExecuted in applicationExecutedList)
            {
                // Executions that fault won't modify storage, so we can skip them.
                if (appExecuted.VMState.HasFlag(VMState.FAULT))
                {
                    continue;
                }
                foreach (var notifyEventArgs in appExecuted.Notifications)
                {
                    if (!(notifyEventArgs?.State is VM.Types.Array stateItems) || stateItems.Count == 0 ||
                        !(notifyEventArgs.ScriptContainer is Transaction transaction))
                    {
                        continue;
                    }
                    HandleNotification(snapshot, transaction, notifyEventArgs.ScriptHash, stateItems,
                                       nep5BalancesChanged, ref transferIndex);
                }
            }

            foreach (var nep5BalancePair in nep5BalancesChanged)
            {
                // get guarantee accurate balances by calling balanceOf for keys that changed.
                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    sb.EmitAppCall(nep5BalancePair.Key.AssetScriptHash, "balanceOf",
                                   nep5BalancePair.Key.UserScriptHash.ToArray());
                    script = sb.ToArray();
                }

                ApplicationEngine engine = ApplicationEngine.Run(script, snapshot);
                if (engine.State.HasFlag(VMState.FAULT))
                {
                    continue;
                }
                if (engine.ResultStack.Count <= 0)
                {
                    continue;
                }
                nep5BalancePair.Value.Balance          = engine.ResultStack.Pop().GetBigInteger();
                nep5BalancePair.Value.LastUpdatedBlock = snapshot.Height;
                if (nep5BalancePair.Value.Balance == 0)
                {
                    _balances.Delete(nep5BalancePair.Key);
                    continue;
                }
                var itemToChange = _balances.GetAndChange(nep5BalancePair.Key, () => nep5BalancePair.Value);
                if (itemToChange != nep5BalancePair.Value)
                {
                    itemToChange.FromReplica(nep5BalancePair.Value);
                }
            }
        }
Example #18
0
        internal static bool VerifyScripts(this IVerifiable verifiable)
        {
            const int max_steps = 1200;

            UInt160[] hashes;
            try
            {
                hashes = verifiable.GetScriptHashesForVerifying();
            }
            catch (InvalidOperationException)
            {
                return(false);
            }
            if (hashes.Length != verifiable.Scripts.Length)
            {
                return(false);
            }
            for (int i = 0; i < hashes.Length; i++)
            {
                byte[] verification = verifiable.Scripts[i].VerificationScript;
                if (verification.Length == 0)
                {
                    using (ScriptBuilder sb = new ScriptBuilder())
                    {
                        sb.EmitAppCall(hashes[i].ToArray());
                        verification = sb.ToArray();
                    }
                }
                else
                {
                    if (hashes[i] != verification.ToScriptHash())
                    {
                        return(false);
                    }
                }
                int             nOpCount = 0;
                ExecutionEngine engine   = new ExecutionEngine(verifiable, Crypto.Default, Blockchain.Default, InterfaceEngine.Default);
                engine.LoadScript(verification, false);
                engine.LoadScript(verifiable.Scripts[i].InvocationScript, true);
                while (!engine.State.HasFlag(VMState.HALT) && !engine.State.HasFlag(VMState.FAULT))
                {
                    if (engine.CurrentContext.InstructionPointer < engine.CurrentContext.Script.Length)
                    {
                        if (++nOpCount > max_steps)
                        {
                            return(false);
                        }
                        if (engine.CurrentContext.NextInstruction == OpCode.CHECKMULTISIG)
                        {
                            if (engine.EvaluationStack.Count == 0)
                            {
                                return(false);
                            }
                            int n = (int)engine.EvaluationStack.Peek().GetBigInteger();
                            if (n < 1)
                            {
                                return(false);
                            }
                            nOpCount += n;
                            if (nOpCount > max_steps)
                            {
                                return(false);
                            }
                        }
                    }
                    engine.StepInto();
                }
                if (engine.State.HasFlag(VMState.FAULT))
                {
                    return(false);
                }
                if (engine.EvaluationStack.Count != 1 || !engine.EvaluationStack.Pop().GetBoolean())
                {
                    return(false);
                }
            }
            return(true);
        }
Example #19
0
        public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS()
        {
            var wallet   = TestUtils.GenerateTestWallet();
            var snapshot = store.GetSnapshot();

            // no password on this wallet
            using (var unlock = wallet.Unlock(""))
            {
                var acc = wallet.CreateAccount();

                // Fake balance

                var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash);

                var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem
                {
                    Value = new Nep5AccountState().ToByteArray()
                });

                entry.Value = new Nep5AccountState()
                {
                    Balance = 10000 * NativeContract.GAS.Factor
                }
                .ToByteArray();

                // Make transaction
                // Manually creating script

                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    // self-transfer of 1e-8 GAS
                    System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value;
                    sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value);
                    sb.Emit(OpCode.THROWIFNOT);
                    script = sb.ToArray();
                }

                // trying two custom hashes, for same target account
                var cosigners = new Cosigner[] { new Cosigner
                                                 {
                                                     Account          = acc.ScriptHash,
                                                     Scopes           = WitnessScope.CustomContracts,
                                                     AllowedContracts = new[] { NativeContract.NEO.Hash, NativeContract.GAS.Hash }
                                                 } };

                // using this...

                var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners);

                Assert.IsNotNull(tx);
                Assert.IsNull(tx.Witnesses);

                // ----
                // Sign
                // ----

                var  data   = new ContractParametersContext(tx);
                bool signed = wallet.Sign(data);
                Assert.IsTrue(signed);

                // get witnesses from signed 'data'
                tx.Witnesses = data.GetWitnesses();
                // only a single witness should exist
                tx.Witnesses.Length.Should().Be(1);
                // no attributes must exist
                tx.Attributes.Length.Should().Be(0);
                // one cosigner must exist
                tx.Cosigners.Length.Should().Be(1);

                // Fast check
                Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee));

                // Check
                long verificationGas = 0;
                foreach (var witness in tx.Witnesses)
                {
                    using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
                    {
                        engine.LoadScript(witness.VerificationScript);
                        engine.LoadScript(witness.InvocationScript);
                        Assert.AreEqual(VMState.HALT, engine.Execute());
                        Assert.AreEqual(1, engine.ResultStack.Count);
                        Assert.IsTrue(engine.ResultStack.Pop().ToBoolean());
                        verificationGas += engine.GasConsumed;
                    }
                }
                // get sizeGas
                var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot);
                // final check on sum: verification_cost + tx_size
                Assert.AreEqual(verificationGas + sizeGas, 1299270);
                // final assert
                Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas);
            }
        }
Example #20
0
        private bool OnInvokeCommand(string[] args)
        {
            var scriptHash = UInt160.Parse(args[1]);

            List <ContractParameter> contractParameters = new List <ContractParameter>();

            for (int i = 3; i < args.Length; i++)
            {
                contractParameters.Add(new ContractParameter()
                {
                    // TODO: support contract params of type other than string.
                    Type  = ContractParameterType.String,
                    Value = args[i]
                });
            }

            Transaction tx = new Transaction
            {
                Sender     = UInt160.Zero,
                Attributes = new TransactionAttribute[0],
                Witness    = new Witness
                {
                    InvocationScript   = new byte[0],
                    VerificationScript = new byte[0]
                }
            };

            using (ScriptBuilder scriptBuilder = new ScriptBuilder())
            {
                scriptBuilder.EmitAppCall(scriptHash, args[2], contractParameters.ToArray());
                tx.Script = scriptBuilder.ToArray();
                Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'");
            }

            ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx);

            Console.WriteLine($"VM State: {engine.State}");
            Console.WriteLine($"Gas Consumed: {engine.GasConsumed}");
            Console.WriteLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToParameter().ToJson()))}");
            Console.WriteLine();
            if (engine.State.HasFlag(VMState.FAULT))
            {
                Console.WriteLine("Engine faulted.");
                return(true);
            }
            if (NoWallet())
            {
                return(true);
            }
            try
            {
                Program.Wallet.FillTransaction(tx);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Error: insufficient balance.");
                return(true);
            }
            if (ReadUserInput("relay tx(no|yes)") != "yes")
            {
                return(true);
            }
            return(SignAndSendTx(tx));
        }
Example #21
0
        public decimal GetBalanceOf(string contract, string address)
        {
//
//            Console.WriteLine("OnPersist script GetBalanceOf contract 1 {0}", contract);
//
//            Console.WriteLine("OnPersist script GetBalanceOf address 2 {0}", address);


            UInt160 script_hash = UInt160.Parse(contract);
            string  operation   = "balanceOf";

            byte[] script;
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                //  var paramas = new JArray();
//                var paramas = new ContractParameter[1];
//                paramas[0].Type =ContractParameterType.Hash160;
//                paramas[0].Value = address;


                //  paramas.Add(c);

                var obj = new JObject();
                obj["type"]  = "Hash160";
                obj["value"] = new UInt160(address.HexToBytes()).ToString();


                // Console.WriteLine("OnPersist script GetBalanceOf obj 3 {0}", obj.ToString());


                var arr = new JArray();
                arr.Add(obj);

                ContractParameter[] parameters = (arr).Select(p => ContractParameter.FromJson(p)).ToArray();
                script = sb.EmitAppCall(script_hash, operation, parameters).ToArray();
            }

            ApplicationEngine engine = ApplicationEngine.Run(script, extraGAS: default(Fixed8));
            var stack = new JArray(engine.ResultStack.Select(p => p.ToParameter().ToJson()));


            if (stack.Count == 0)
            {
                return(0);
            }

//            Console.WriteLine("OnPersist script GetBalanceOf obj 4 {0}", stack.ToString());
//
//            Console.WriteLine("OnPersist script GetBalanceOf 5 {0}", stack[0]["value"].ToString());

            if (stack[0]["value"].AsString() == "")
            {
                return(0);
            }

            // return 1;
//            return int.Parse(stack[0]["value"].AsString());

            var de = GetDecimals(contract);

            if (stack[0]["type"].AsString() == "ByteArray" &&
                !string.IsNullOrEmpty(stack[0]["value"].AsString()))
            {
                var handleValue =
                    ((new BigInteger(stack[0]["value"].AsString().HexToBytes())) /
                     new BigInteger(Math.Pow(10, de
                                             )));

//                                            var handleValue = ((new BigInteger("00ac23fc06".HexToBytes())) /
//                                                               new BigInteger(Math.Pow(10, GetDecimals())));


//                Console.WriteLine("OnPersist script GetBalanceOf 5 {0}",
//                    decimal.Parse(handleValue.ToString(), NumberStyles.Any));
                return(decimal.Parse(handleValue.ToString(), NumberStyles.Any));
            }


            if (stack[0]["type"].AsString() == "Integer" && !string.IsNullOrEmpty(stack[0]["value"].AsString()))
            {
                var handleValue = (Double.Parse(stack[0]["value"].AsString()) /
                                   Math.Pow(10, de));


                return(decimal.Parse(handleValue.ToString(), NumberStyles.Any));
            }

            return(0);
        }
Example #22
0
        async Task test_mintTokens()
        {
            decimal amount = 0;

            while (true)
            {
                subPrintLine("Input amount:");
                string str_amount = Console.ReadLine();
                try
                {
                    amount = decimal.Parse(str_amount);
                    break;
                }
                catch (Exception e)
                {
                    subPrintLine("input number");
                }
            }

            //获取地址的资产列表
            Dictionary <string, List <Utxo> > dir = await Helper.GetBalanceByAddress(Config.api, address);

            if (dir.ContainsKey(Config.id_GAS) == false)
            {
                subPrintLine("no gas");
                return;
            }
            Transaction tran = null;
            {
                byte[] script = null;
                using (var sb = new ScriptBuilder())
                {
                    var array = new MyJson.JsonNode_Array();
                    sb.EmitParamJson(array);                                              //参数倒序入
                    sb.EmitParamJson(new MyJson.JsonNode_ValueString("(str)mintTokens")); //参数倒序入
                    Hash160 shash = Config.dapp_sgas;
                    sb.EmitAppCall(shash);                                                //nep5脚本
                    script = sb.ToArray();
                }
                var sgasScripthash = Config.dapp_sgas;
                var targetaddr     = ThinNeo.Helper.GetAddressFromScriptHash(sgasScripthash);
                subPrintLine("contract address=" + targetaddr);//往合约地址转账

                //生成交易
                tran      = Helper.makeTran(dir[Config.id_GAS], targetaddr, new Hash256(Config.id_GAS), amount);
                tran.type = TransactionType.InvocationTransaction;
                var idata = new InvokeTransData();
                tran.extdata = idata;
                idata.script = script;

                //sign and broadcast
                var signdata = ThinNeo.Helper.Sign(tran.GetMessage(), prikey);
                tran.AddWitness(signdata, pubkey, address);
                var    trandata    = tran.GetRawData();
                var    strtrandata = ThinNeo.Helper.Bytes2HexString(trandata);
                byte[] postdata;
                var    url    = Helper.MakeRpcUrlPost(Config.api, "sendrawtransaction", out postdata, new MyJson.JsonNode_ValueString(strtrandata));
                var    result = await Helper.HttpPost(url, postdata);

                subPrintLine("得到的结果是:" + result);
                var json = MyJson.Parse(result).AsDict();
                if (json.ContainsKey("result"))
                {
                    var resultv = json["result"].AsList()[0].AsDict();
                    var txid    = resultv["txid"].AsString();
                    subPrintLine("txid=" + txid);
                }
            }
        }
Example #23
0
        private JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "dumpprivkey":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UInt160       scriptHash = _params[0].AsString().ToScriptHash();
                    WalletAccount account    = wallet.GetAccount(scriptHash);
                    return(account.GetKey().Export());
                }

            case "getaccountstate":
            {
                UInt160      script_hash = _params[0].AsString().ToScriptHash();
                AccountState account     = Blockchain.Singleton.Store.GetAccounts().TryGet(script_hash) ?? new AccountState(script_hash);
                return(account.ToJson());
            }

            case "getassetstate":
            {
                UInt256    asset_id = UInt256.Parse(_params[0].AsString());
                AssetState asset    = Blockchain.Singleton.Store.GetAssets().TryGet(asset_id);
                return(asset?.ToJson() ?? throw new RpcException(-100, "Unknown asset"));
            }

            case "getbalance":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    JObject json = new JObject();
                    switch (UIntBase.Parse(_params[0].AsString()))
                    {
                    case UInt160 asset_id_160:         //NEP-5 balance
                        json["balance"] = wallet.GetAvailable(asset_id_160).ToString();
                        break;

                    case UInt256 asset_id_256:         //Global Assets balance
                        IEnumerable <Coin> coins = wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(asset_id_256));
                        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();
                        break;
                    }
                    return(json);
                }

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

            case "getblock":
            {
                Block block;
                if (_params[0] is JNumber)
                {
                    uint index = (uint)_params[0].AsNumber();
                    block = Blockchain.Singleton.Store.GetBlock(index);
                }
                else
                {
                    UInt256 hash = UInt256.Parse(_params[0].AsString());
                    block = Blockchain.Singleton.Store.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.Singleton.Height - block.Index + 1;
                    UInt256 hash = Blockchain.Singleton.Store.GetNextBlockHash(block.Hash);
                    if (hash != null)
                    {
                        json["nextblockhash"] = hash.ToString();
                    }
                    return(json);
                }
                return(block.ToArray().ToHexString());
            }

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

            case "getblockhash":
            {
                uint height = (uint)_params[0].AsNumber();
                if (height <= Blockchain.Singleton.Height)
                {
                    return(Blockchain.Singleton.GetBlockHash(height).ToString());
                }
                throw new RpcException(-100, "Invalid Height");
            }

            case "getblockheader":
            {
                Header header;
                if (_params[0] is JNumber)
                {
                    uint height = (uint)_params[0].AsNumber();
                    header = Blockchain.Singleton.Store.GetHeader(height);
                }
                else
                {
                    UInt256 hash = UInt256.Parse(_params[0].AsString());
                    header = Blockchain.Singleton.Store.GetHeader(hash);
                }
                if (header == null)
                {
                    throw new RpcException(-100, "Unknown block");
                }

                bool verbose = _params.Count >= 2 && _params[1].AsBooleanOrDefault(false);
                if (verbose)
                {
                    JObject json = header.ToJson();
                    json["confirmations"] = Blockchain.Singleton.Height - header.Index + 1;
                    UInt256 hash = Blockchain.Singleton.Store.GetNextBlockHash(header.Hash);
                    if (hash != null)
                    {
                        json["nextblockhash"] = hash.ToString();
                    }
                    return(json);
                }

                return(header.ToArray().ToHexString());
            }

            case "getblocksysfee":
            {
                uint height = (uint)_params[0].AsNumber();
                if (height <= Blockchain.Singleton.Height)
                {
                    return(Blockchain.Singleton.Store.GetSysFeeAmount(height).ToString());
                }
                throw new RpcException(-100, "Invalid Height");
            }

            case "getconnectioncount":
                return(LocalNode.Singleton.ConnectedCount);

            case "getcontractstate":
            {
                UInt160       script_hash = UInt160.Parse(_params[0].AsString());
                ContractState contract    = Blockchain.Singleton.Store.GetContracts().TryGet(script_hash);
                return(contract?.ToJson() ?? throw new RpcException(-100, "Unknown contract"));
            }

            case "getnewaddress":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    WalletAccount account = wallet.CreateAccount();
                    if (wallet is TERC1Wallet nep6)
                    {
                        nep6.Save();
                    }
                    return(account.Address);
                }

            case "getpeers":
            {
                JObject json = new JObject();
                json["unconnected"] = new JArray(LocalNode.Singleton.GetUnconnectedPeers().Select(p =>
                    {
                        JObject peerJson    = new JObject();
                        peerJson["address"] = p.Address.ToString();
                        peerJson["port"]    = p.Port;
                        return(peerJson);
                    }));
                json["bad"]       = new JArray();   //badpeers has been removed
                json["connected"] = new JArray(LocalNode.Singleton.GetRemoteNodes().Select(p =>
                    {
                        JObject peerJson    = new JObject();
                        peerJson["address"] = p.Remote.Address.ToString();
                        peerJson["port"]    = p.ListenerPort;
                        return(peerJson);
                    }));
                return(json);
            }

            case "getrawmempool":
                return(new JArray(Blockchain.Singleton.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);
                Transaction tx      = Blockchain.Singleton.GetTransaction(hash);
                if (tx == null)
                {
                    throw new RpcException(-100, "Unknown transaction");
                }
                if (verbose)
                {
                    JObject json   = tx.ToJson();
                    uint?   height = Blockchain.Singleton.Store.GetTransactions().TryGet(hash)?.BlockIndex;
                    if (height != null)
                    {
                        Header header = Blockchain.Singleton.Store.GetHeader((uint)height);
                        json["blockhash"]     = header.Hash.ToString();
                        json["confirmations"] = Blockchain.Singleton.Height - header.Index + 1;
                        json["blocktime"]     = header.Timestamp;
                    }
                    return(json);
                }
                return(tx.ToArray().ToHexString());
            }

            case "getstorage":
            {
                UInt160     script_hash = UInt160.Parse(_params[0].AsString());
                byte[]      key         = _params[1].AsString().HexToBytes();
                StorageItem item        = Blockchain.Singleton.Store.GetStorages().TryGet(new StorageKey
                    {
                        ScriptHash = script_hash,
                        Key        = key
                    }) ?? new StorageItem();
                return(item.Value?.ToHexString());
            }

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

            case "getvalidators":
                using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
                {
                    var validators = snapshot.GetValidators();
                    return(snapshot.GetEnrollments().Select(p =>
                    {
                        JObject validator = new JObject();
                        validator["publickey"] = p.PublicKey.ToString();
                        validator["votes"] = p.Votes.ToString();
                        validator["active"] = validators.Contains(p.PublicKey);
                        return validator;
                    }).ToArray());
                }

            case "getversion":
            {
                JObject json = new JObject();
                json["port"]      = LocalNode.Singleton.ListenerPort;
                json["nonce"]     = LocalNode.Nonce;
                json["useragent"] = LocalNode.UserAgent;
                return(json);
            }

            case "getwalletheight":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    return((wallet.WalletHeight > 0) ? wallet.WalletHeight - 1 : 0);
                }

            case "invoke":
            {
                UInt160             script_hash = UInt160.Parse(_params[0].AsString());
                ContractParameter[] parameters  = ((JArray)_params[1]).Select(p => ContractParameter.FromJson(p)).ToArray();
                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    script = sb.EmitAppCall(script_hash, parameters).ToArray();
                }
                return(GetInvokeResult(script));
            }

            case "invokefunction":
            {
                UInt160             script_hash = UInt160.Parse(_params[0].AsString());
                string              operation   = _params[1].AsString();
                ContractParameter[] args        = _params.Count >= 3 ? ((JArray)_params[2]).Select(p => ContractParameter.FromJson(p)).ToArray() : new ContractParameter[0];
                byte[]              script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    script = sb.EmitAppCall(script_hash, operation, args).ToArray();
                }
                return(GetInvokeResult(script));
            }

            case "invokescript":
            {
                byte[] script = _params[0].AsString().HexToBytes();
                return(GetInvokeResult(script));
            }

            case "listaddress":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    return(wallet.GetAccounts().Select(p =>
                    {
                        JObject account = new JObject();
                        account["address"] = p.Address;
                        account["haskey"] = p.HasKey;
                        account["label"] = p.Label;
                        account["watchonly"] = p.WatchOnly;
                        return account;
                    }).ToArray());
                }

            case "sendfrom":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UIntBase        assetId    = UIntBase.Parse(_params[0].AsString());
                    AssetDescriptor descriptor = new AssetDescriptor(assetId);
                    UInt160         from       = _params[1].AsString().ToScriptHash();
                    UInt160         to         = _params[2].AsString().ToScriptHash();
                    BigDecimal      value      = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals);
                    if (value.Sign <= 0)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero;
                    if (fee < Fixed8.Zero)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    UInt160     change_address = _params.Count >= 6 ? _params[5].AsString().ToScriptHash() : null;
                    Transaction tx             = wallet.MakeTransaction(null, new[]
                    {
                        new TransferOutput
                        {
                            AssetId    = assetId,
                            Value      = value,
                            ScriptHash = to
                        }
                    }, from: from, change_address: change_address, fee: fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    ContractParametersContext context = new ContractParametersContext(tx);
                    wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Witnesses = context.GetWitnesses();
                        wallet.ApplyTransaction(tx);
                        system.LocalNode.Tell(new LocalNode.Relay {
                            Inventory = tx
                        });
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "sendmany":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    JArray to = (JArray)_params[0];
                    if (to.Count == 0)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    TransferOutput[] outputs = new TransferOutput[to.Count];
                    for (int i = 0; i < to.Count; i++)
                    {
                        UIntBase        asset_id   = UIntBase.Parse(to[i]["asset"].AsString());
                        AssetDescriptor descriptor = new AssetDescriptor(asset_id);
                        outputs[i] = new TransferOutput
                        {
                            AssetId    = asset_id,
                            Value      = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals),
                            ScriptHash = to[i]["address"].AsString().ToScriptHash()
                        };
                        if (outputs[i].Value.Sign <= 0)
                        {
                            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 ? _params[2].AsString().ToScriptHash() : null;
                    Transaction tx             = wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    ContractParametersContext context = new ContractParametersContext(tx);
                    wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Witnesses = context.GetWitnesses();
                        wallet.ApplyTransaction(tx);
                        system.LocalNode.Tell(new LocalNode.Relay {
                            Inventory = tx
                        });
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "sendrawtransaction":
            {
                Transaction       tx     = Transaction.DeserializeFrom(_params[0].AsString().HexToBytes());
                RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(tx).Result;
                return(GetRelayResult(reason));
            }

            case "sendtoaddress":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UIntBase        assetId    = UIntBase.Parse(_params[0].AsString());
                    AssetDescriptor descriptor = new AssetDescriptor(assetId);
                    UInt160         scriptHash = _params[1].AsString().ToScriptHash();
                    BigDecimal      value      = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals);
                    if (value.Sign <= 0)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero;
                    if (fee < Fixed8.Zero)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    UInt160     change_address = _params.Count >= 5 ? _params[4].AsString().ToScriptHash() : null;
                    Transaction tx             = wallet.MakeTransaction(null, new[]
                    {
                        new TransferOutput
                        {
                            AssetId    = assetId,
                            Value      = value,
                            ScriptHash = scriptHash
                        }
                    }, change_address: change_address, fee: fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    ContractParametersContext context = new ContractParametersContext(tx);
                    wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Witnesses = context.GetWitnesses();
                        wallet.ApplyTransaction(tx);
                        system.LocalNode.Tell(new LocalNode.Relay {
                            Inventory = tx
                        });
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "submitblock":
            {
                Block             block  = _params[0].AsString().HexToBytes().AsSerializable <Block>();
                RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(block).Result;
                return(GetRelayResult(reason));
            }

            case "validateaddress":
            {
                JObject json = new JObject();
                UInt160 scriptHash;
                try
                {
                    scriptHash = _params[0].AsString().ToScriptHash();
                }
                catch
                {
                    scriptHash = null;
                }
                json["address"] = _params[0];
                json["isvalid"] = scriptHash != null;
                return(json);
            }

            default:
                throw new RpcException(-32601, "Method not found");
            }
        }
Example #24
0
        public Transaction GetTransaction()
        {
            var cOutputs = txOutListBox1.Items.Where(p => p.AssetId is UInt160).GroupBy(p => new
            {
                AssetId = (UInt160)p.AssetId,
                Account = p.ScriptHash
            }, (k, g) => new
            {
                k.AssetId,
                Value = g.Aggregate(BigInteger.Zero, (x, y) => x + y.Value.Value),
                k.Account
            }).ToArray();
            Transaction tx;
            List <TransactionAttribute> attributes = new List <TransactionAttribute>();

            if (comboBoxFrom.SelectedItem == null)
            {
                FromAddress = null;
            }
            else
            {
                FromAddress = ((string)comboBoxFrom.SelectedItem).ToScriptHash();
            }

            if (cOutputs.Length == 0)
            {
                tx = new ContractTransaction();
            }
            else
            {
                UInt160[] addresses;
                if (FromAddress != null)
                {
                    addresses = Program.CurrentWallet.GetAccounts().Where(e => e.ScriptHash.Equals(FromAddress)).Select(p => p.ScriptHash).ToArray();
                }
                else
                {
                    addresses = Program.CurrentWallet.GetAccounts().Where(e => !e.WatchOnly).Select(p => p.ScriptHash).ToArray();
                }
                HashSet <UInt160> sAttributes = new HashSet <UInt160>();
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    foreach (var output in cOutputs)
                    {
                        byte[] script;
                        using (ScriptBuilder sb2 = new ScriptBuilder())
                        {
                            foreach (UInt160 address in addresses)
                            {
                                sb2.EmitAppCall(output.AssetId, "balanceOf", address);
                            }

                            sb2.Emit(OpCode.DEPTH, OpCode.PACK);
                            script = sb2.ToArray();
                        }
                        ApplicationEngine engine = ApplicationEngine.Run(script);
                        if (engine.State.HasFlag(VMState.FAULT))
                        {
                            return(null);
                        }
                        var balances = ((VMArray)engine.ResultStack.Pop()).AsEnumerable().Reverse().Zip(addresses, (i, a) => new
                        {
                            Account = a,
                            Value   = i.GetBigInteger()
                        }).Where(p => p.Value != 0).ToArray();

                        BigInteger sum = balances.Aggregate(BigInteger.Zero, (x, y) => x + y.Value);
                        if (sum < output.Value)
                        {
                            return(null);
                        }
                        if (sum != output.Value)
                        {
                            balances = balances.OrderByDescending(p => p.Value).ToArray();
                            BigInteger amount = output.Value;
                            int        i      = 0;
                            while (balances[i].Value <= amount)
                            {
                                amount -= balances[i++].Value;
                            }
                            if (amount == BigInteger.Zero)
                            {
                                balances = balances.Take(i).ToArray();
                            }
                            else
                            {
                                balances = balances.Take(i).Concat(new[] { balances.Last(p => p.Value >= amount) }).ToArray();
                            }
                            sum = balances.Aggregate(BigInteger.Zero, (x, y) => x + y.Value);
                        }
                        sAttributes.UnionWith(balances.Select(p => p.Account));
                        for (int i = 0; i < balances.Length; i++)
                        {
                            BigInteger value = balances[i].Value;
                            if (i == 0)
                            {
                                BigInteger change = sum - output.Value;
                                if (change > 0)
                                {
                                    value -= change;
                                }
                            }
                            sb.EmitAppCall(output.AssetId, "transfer", balances[i].Account, output.Account, value);
                            sb.Emit(OpCode.THROWIFNOT);
                        }
                    }
                    tx = new InvocationTransaction
                    {
                        Version = 1,
                        Script  = sb.ToArray()
                    };
                }
                attributes.AddRange(sAttributes.Select(p => new TransactionAttribute
                {
                    Usage = TransactionAttributeUsage.Script,
                    Data  = p.ToArray()
                }));
            }
            if (!string.IsNullOrEmpty(remark))
            {
                attributes.Add(new TransactionAttribute
                {
                    Usage = TransactionAttributeUsage.Remark,
                    Data  = Encoding.UTF8.GetBytes(remark)
                });
            }
            tx.Attributes = attributes.ToArray();
            tx.Outputs    = txOutListBox1.Items.Where(p => p.AssetId is UInt256).Select(p => p.ToTxOutput()).ToArray();
            var tempOuts = tx.Outputs;

            if (tx is ContractTransaction copyTx)
            {
                copyTx.Witnesses = new Witness[0];
                copyTx           = Program.CurrentWallet.MakeTransaction(copyTx, FromAddress, change_address: ChangeAddress, fee: Fee);
                if (copyTx == null)
                {
                    return(null);
                }
                ContractParametersContext transContext = new ContractParametersContext(copyTx);
                Program.CurrentWallet.Sign(transContext);
                if (transContext.Completed)
                {
                    copyTx.Witnesses = transContext.GetWitnesses();
                }
                if (copyTx.Size > 1024)
                {
                    Fixed8 PriorityFee = Fixed8.FromDecimal(0.001m) + Fixed8.FromDecimal(copyTx.Size * 0.00001m);
                    if (Fee > PriorityFee)
                    {
                        PriorityFee = Fee;
                    }
                    if (!Helper.CostRemind(Fixed8.Zero, PriorityFee))
                    {
                        return(null);
                    }
                    tx = Program.CurrentWallet.MakeTransaction(new ContractTransaction
                    {
                        Outputs    = tempOuts,
                        Attributes = tx.Attributes
                    }, FromAddress, change_address: ChangeAddress, fee: PriorityFee);
                }
            }
            return(tx);
        }
Example #25
0
        public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS()
        {
            var wallet   = TestUtils.GenerateTestWallet();
            var snapshot = Blockchain.Singleton.GetSnapshot();

            // no password on this wallet
            using (var unlock = wallet.Unlock(""))
            {
                var acc = wallet.CreateAccount();

                // Fake balance

                var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash);

                var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState()));

                entry.GetInteroperable <Nep5AccountState>().Balance = 10000 * NativeContract.GAS.Factor;

                snapshot.Commit();

                // Make transaction
                // Manually creating script

                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    // self-transfer of 1e-8 GAS
                    System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value;
                    sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value);
                    sb.Emit(OpCode.ASSERT);
                    script = sb.ToArray();
                }

                // trying CalledByEntry together with GAS
                var cosigners = new Cosigner[] { new Cosigner
                                                 {
                                                     Account = acc.ScriptHash,
                                                     // This combination is supposed to actually be an OR,
                                                     // where it's valid in both Entry and also for Custom hash provided (in any execution level)
                                                     // it would be better to test this in the future including situations where a deeper call level uses this custom witness successfully
                                                     Scopes           = WitnessScope.CustomContracts | WitnessScope.CalledByEntry,
                                                     AllowedContracts = new[] { NativeContract.GAS.Hash }
                                                 } };

                // using this...

                var tx = wallet.MakeTransaction(script, acc.ScriptHash, cosigners);

                Assert.IsNotNull(tx);
                Assert.IsNull(tx.Witnesses);

                // ----
                // Sign
                // ----

                var  data   = new ContractParametersContext(tx);
                bool signed = wallet.Sign(data);
                Assert.IsTrue(signed);

                // get witnesses from signed 'data'
                tx.Witnesses = data.GetWitnesses();
                tx.Witnesses.Length.Should().Be(1);

                // Fast check
                Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee));

                // Check
                long verificationGas = 0;
                foreach (var witness in tx.Witnesses)
                {
                    using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
                    {
                        engine.LoadScript(witness.VerificationScript);
                        engine.LoadScript(witness.InvocationScript);
                        Assert.AreEqual(VMState.HALT, engine.Execute());
                        Assert.AreEqual(1, engine.ResultStack.Count);
                        Assert.IsTrue(engine.ResultStack.Pop().ToBoolean());
                        verificationGas += engine.GasConsumed;
                    }
                }
                // get sizeGas
                var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot);
                // final check on sum: verification_cost + tx_size
                Assert.AreEqual(1285390, verificationGas + sizeGas);
                // final assert
                Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas);
            }
        }
Example #26
0
        public void TestParallel()
        {
            var args = new ExecutionEngineArgs()
            {
                ScriptTable = new DummyScriptTable
                              (
                    new byte[] { (byte)EVMOpCode.EQUAL },
                    new byte[] { (byte)EVMOpCode.EQUAL }
                              )
            };

            // 5 Scripts

            var engines = new List <ExecutionEngineBase>()
            {
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args),
                CreateEngine(args)
            };

            Parallel.ForEach(engines, (engine) =>
            {
                using (engine)
                {
                    for (ushort x = 0; x < 1000; x++)
                    {
                        // Load script

                        engine.Clean(x);

                        using (var script = new ScriptBuilder())
                        {
                            script.EmitPush(x);
                            script.EmitPush(x);
                            script.EmitAppCall(new byte[]
                            {
                                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
                                0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
                            });

                            engine.LoadScript(script);
                        }

                        // Execute

                        Assert.IsTrue(engine.Execute());

                        // Check result

                        using (var it = engine.ResultStack.Pop <BooleanStackItem>())
                        {
                            Assert.IsTrue(it.Value);
                        }
                    }
                }
            });
        }
Example #27
0
        private void timer1_Tick(object sender, EventArgs e)
        {
            lbl_height.Text = $"{Blockchain.Singleton.Height}/{Blockchain.Singleton.HeaderHeight}";

            lbl_count_node.Text = LocalNode.Singleton.ConnectedCount.ToString();
            TimeSpan persistence_span = DateTime.UtcNow - persistence_time;

            if (persistence_span < TimeSpan.Zero)
            {
                persistence_span = TimeSpan.Zero;
            }
            if (persistence_span > Blockchain.TimePerBlock)
            {
                toolStripProgressBar1.Style = ProgressBarStyle.Marquee;
            }
            else
            {
                toolStripProgressBar1.Value = persistence_span.Seconds;
                toolStripProgressBar1.Style = ProgressBarStyle.Blocks;
            }
            if (Service.CurrentWallet is null)
            {
                return;
            }
            if (!check_nep5_balance || persistence_span < TimeSpan.FromSeconds(2))
            {
                return;
            }
            check_nep5_balance = false;
            UInt160[] addresses = Service.CurrentWallet.GetAccounts().Select(p => p.ScriptHash).ToArray();
            if (addresses.Length == 0)
            {
                return;
            }
            using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot();
            foreach (UInt160 assetId in NEP5Watched)
            {
                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    for (int i = addresses.Length - 1; i >= 0; i--)
                    {
                        sb.EmitAppCall(assetId, "balanceOf", addresses[i]);
                    }
                    sb.Emit(OpCode.DEPTH, OpCode.PACK);
                    sb.EmitAppCall(assetId, "decimals");
                    sb.EmitAppCall(assetId, "name");
                    script = sb.ToArray();
                }
                using ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, extraGAS: 0_20000000L * addresses.Length);
                if (engine.State.HasFlag(VMState.FAULT))
                {
                    continue;
                }
                string       name     = engine.ResultStack.Pop().GetString();
                byte         decimals = (byte)engine.ResultStack.Pop().GetBigInteger();
                BigInteger[] balances = ((VMArray)engine.ResultStack.Pop()).Select(p => p.GetBigInteger()).ToArray();
                string       symbol   = null;
                if (assetId.Equals(NativeContract.NEO.Hash))
                {
                    symbol = NativeContract.NEO.Symbol;
                }
                else if (assetId.Equals(NativeContract.GAS.Hash))
                {
                    symbol = NativeContract.GAS.Symbol;
                }
                if (symbol != null)
                {
                    for (int i = 0; i < addresses.Length; i++)
                    {
                        listView1.Items[addresses[i].ToAddress()].SubItems[symbol].Text = new BigDecimal(balances[i], decimals).ToString();
                    }
                }
                BigInteger amount = balances.Sum();
                if (amount == 0)
                {
                    listView2.Items.RemoveByKey(assetId.ToString());
                    continue;
                }
                BigDecimal balance = new BigDecimal(amount, decimals);
                if (listView2.Items.ContainsKey(assetId.ToString()))
                {
                    listView2.Items[assetId.ToString()].SubItems["value"].Text = balance.ToString();
                }
                else
                {
                    listView2.Items.Add(new ListViewItem(new[]
                    {
                        new ListViewItem.ListViewSubItem
                        {
                            Name = "name",
                            Text = name
                        },
                        new ListViewItem.ListViewSubItem
                        {
                            Name = "type",
                            Text = "NEP-5"
                        },
                        new ListViewItem.ListViewSubItem
                        {
                            Name = "value",
                            Text = balance.ToString()
                        },
                        new ListViewItem.ListViewSubItem
                        {
                            ForeColor = Color.Gray,
                            Name      = "issuer",
                            Text      = $"ScriptHash:{assetId}"
                        }
                    }, -1)
                    {
                        Name = assetId.ToString(),
                        UseItemStyleForSubItems = false
                    });
                }
            }
        }
Example #28
0
        public void Runtime_GetNotifications_Test()
        {
            UInt160 scriptHash2;
            var     snapshot = Blockchain.Singleton.GetSnapshot();

            using (var script = new ScriptBuilder())
            {
                // Notify method

                script.Emit(OpCode.SWAP, OpCode.NEWARRAY, OpCode.SWAP);
                script.EmitSysCall(ApplicationEngine.System_Runtime_Notify);

                // Add return

                script.EmitPush(true);
                script.Emit(OpCode.RET);

                // Mock contract

                scriptHash2 = script.ToArray().ToScriptHash();

                snapshot.Contracts.Delete(scriptHash2);
                snapshot.Contracts.Add(scriptHash2, new ContractState()
                {
                    Script   = script.ToArray(),
                    Manifest = TestUtils.CreateManifest(scriptHash2, "test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer),
                });
            }

            // Wrong length

            using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
                using (var script = new ScriptBuilder())
                {
                    // Retrive

                    script.EmitPush(1);
                    script.EmitSysCall(ApplicationEngine.System_Runtime_GetNotifications);

                    // Execute

                    engine.LoadScript(script.ToArray());

                    Assert.AreEqual(VMState.FAULT, engine.Execute());
                }

            // All test

            using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
                using (var script = new ScriptBuilder())
                {
                    // Notification

                    script.EmitPush(0);
                    script.Emit(OpCode.NEWARRAY);
                    script.EmitPush("testEvent1");
                    script.EmitSysCall(ApplicationEngine.System_Runtime_Notify);

                    // Call script

                    script.EmitAppCall(scriptHash2, ContractParameterType.Any, "test", "testEvent2", 1);

                    // Drop return

                    script.Emit(OpCode.DROP);

                    // Receive all notifications

                    script.Emit(OpCode.PUSHNULL);
                    script.EmitSysCall(ApplicationEngine.System_Runtime_GetNotifications);

                    // Execute

                    engine.LoadScript(script.ToArray());
                    var currentScriptHash = engine.EntryScriptHash;

                    Assert.AreEqual(VMState.HALT, engine.Execute());
                    Assert.AreEqual(1, engine.ResultStack.Count);
                    Assert.AreEqual(2, engine.Notifications.Count);

                    Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(VM.Types.Array));

                    var array = (VM.Types.Array)engine.ResultStack.Pop();

                    // Check syscall result

                    AssertNotification(array[1], scriptHash2, "testEvent2");
                    AssertNotification(array[0], currentScriptHash, "testEvent1");

                    // Check notifications

                    Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash);
                    Assert.AreEqual("testEvent2", engine.Notifications[1].EventName);

                    Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash);
                    Assert.AreEqual("testEvent1", engine.Notifications[0].EventName);
                }

            // Script notifications

            using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
                using (var script = new ScriptBuilder())
                {
                    // Notification

                    script.EmitPush(0);
                    script.Emit(OpCode.NEWARRAY);
                    script.EmitPush("testEvent1");
                    script.EmitSysCall(ApplicationEngine.System_Runtime_Notify);

                    // Call script

                    script.EmitAppCall(scriptHash2, ContractParameterType.Any, "test", "testEvent2", 1);

                    // Drop return

                    script.Emit(OpCode.DROP);

                    // Receive all notifications

                    script.EmitPush(scriptHash2.ToArray());
                    script.EmitSysCall(ApplicationEngine.System_Runtime_GetNotifications);

                    // Execute

                    engine.LoadScript(script.ToArray());
                    var currentScriptHash = engine.EntryScriptHash;

                    Assert.AreEqual(VMState.HALT, engine.Execute());
                    Assert.AreEqual(1, engine.ResultStack.Count);
                    Assert.AreEqual(2, engine.Notifications.Count);

                    Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(VM.Types.Array));

                    var array = (VM.Types.Array)engine.ResultStack.Pop();

                    // Check syscall result

                    AssertNotification(array[0], scriptHash2, "testEvent2");

                    // Check notifications

                    Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash);
                    Assert.AreEqual("testEvent2", engine.Notifications[1].EventName);

                    Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash);
                    Assert.AreEqual("testEvent1", engine.Notifications[0].EventName);
                }

            // Clean storage

            snapshot.Contracts.Delete(scriptHash2);
        }
Example #29
0
        protected virtual JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "getaccountstate":
            {
                UInt160      script_hash = Wallet.ToScriptHash(_params[0].AsString());
                AccountState account     = Blockchain.Default.GetAccountState(script_hash) ?? new AccountState(script_hash);
                return(account.ToJson());
            }

            case "getassetstate":
            {
                UInt256    asset_id = UInt256.Parse(_params[0].AsString());
                AssetState asset    = Blockchain.Default.GetAssetState(asset_id);
                return(asset?.ToJson() ?? throw new RpcException(-100, "Unknown asset"));
            }

            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.Index + 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();
                if (height >= 0 && height <= Blockchain.Default.Height)
                {
                    return(Blockchain.Default.GetBlockHash(height).ToString());
                }
                else
                {
                    throw new RpcException(-100, "Invalid Height");
                }
            }

            case "getblocksysfee":
            {
                uint height = (uint)_params[0].AsNumber();
                if (height >= 0 && height <= Blockchain.Default.Height)
                {
                    return(Blockchain.Default.GetSysFeeAmount(height).ToString());
                }
                else
                {
                    throw new RpcException(-100, "Invalid Height");
                }
            }

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

            case "getcontractstate":
            {
                UInt160       script_hash = UInt160.Parse(_params[0].AsString());
                ContractState contract    = Blockchain.Default.GetContract(script_hash);
                return(contract?.ToJson() ?? throw new RpcException(-100, "Unknown contract"));
            }

            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(-100, "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.Index + 1;
                        json["blocktime"]     = header.Timestamp;
                    }
                    return(json);
                }
                else
                {
                    return(tx.ToArray().ToHexString());
                }
            }

            case "getstorage":
            {
                UInt160     script_hash = UInt160.Parse(_params[0].AsString());
                byte[]      key         = _params[1].AsString().HexToBytes();
                StorageItem item        = Blockchain.Default.GetStorageItem(new StorageKey
                    {
                        ScriptHash = script_hash,
                        Key        = key
                    }) ?? new StorageItem();
                return(item.Value?.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 "getvalidators":
            {
                var validators = Blockchain.Default.GetValidators();
                return(Blockchain.Default.GetEnrollments().Select(p =>
                    {
                        JObject validator = new JObject();
                        validator["publickey"] = p.PublicKey.ToString();
                        validator["votes"] = p.Votes.ToString();
                        validator["active"] = validators.Contains(p.PublicKey);
                        return validator;
                    }).ToArray());
            }

            case "invoke":
            {
                UInt160             script_hash = UInt160.Parse(_params[0].AsString());
                ContractParameter[] parameters  = ((JArray)_params[1]).Select(p => ContractParameter.FromJson(p)).ToArray();
                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    script = sb.EmitAppCall(script_hash, parameters).ToArray();
                }
                return(GetInvokeResult(script));
            }

            case "invokefunction":
            {
                UInt160             script_hash = UInt160.Parse(_params[0].AsString());
                string              operation   = _params[1].AsString();
                ContractParameter[] args        = _params.Count >= 3 ? ((JArray)_params[2]).Select(p => ContractParameter.FromJson(p)).ToArray() : new ContractParameter[0];
                byte[]              script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    script = sb.EmitAppCall(script_hash, operation, args).ToArray();
                }
                return(GetInvokeResult(script));
            }

            case "invokescript":
            {
                byte[] script = _params[0].AsString().HexToBytes();
                return(GetInvokeResult(script));
            }

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

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

            case "validateaddress":
            {
                JObject json = new JObject();
                UInt160 scriptHash;
                try
                {
                    scriptHash = Wallet.ToScriptHash(_params[0].AsString());
                }
                catch
                {
                    scriptHash = null;
                }
                json["address"] = _params[0];
                json["isvalid"] = scriptHash != null;
                return(json);
            }

            case "getpeers":
            {
                JObject json = new JObject();

                {
                    JArray unconnectedPeers = new JArray();
                    foreach (IPEndPoint peer in LocalNode.GetUnconnectedPeers())
                    {
                        JObject peerJson = new JObject();
                        peerJson["address"] = peer.Address.ToString();
                        peerJson["port"]    = peer.Port;
                        unconnectedPeers.Add(peerJson);
                    }
                    json["unconnected"] = unconnectedPeers;
                }

                {
                    JArray badPeers = new JArray();
                    foreach (IPEndPoint peer in LocalNode.GetBadPeers())
                    {
                        JObject peerJson = new JObject();
                        peerJson["address"] = peer.Address.ToString();
                        peerJson["port"]    = peer.Port;
                        badPeers.Add(peerJson);
                    }
                    json["bad"] = badPeers;
                }

                {
                    JArray connectedPeers = new JArray();
                    foreach (RemoteNode node in LocalNode.GetRemoteNodes())
                    {
                        JObject peerJson = new JObject();
                        peerJson["address"] = node.RemoteEndpoint.Address.ToString();
                        peerJson["port"]    = node.ListenerEndpoint?.Port ?? 0;
                        connectedPeers.Add(peerJson);
                    }
                    json["connected"] = connectedPeers;
                }

                return(json);
            }

            case "getversion":
            {
                JObject json = new JObject();
                json["port"]      = LocalNode.Port;
                json["nonce"]     = LocalNode.Nonce;
                json["useragent"] = LocalNode.UserAgent;
                return(json);
            }

            case "createwallet":
            {
                JObject json = new JObject();
                return(json);
            }

            default:
                throw new RpcException(-32601, "Method not found");
            }
        }
Example #30
0
        public void Run()
        {
            string  wif           = "KwwJMvfFPcRx2HSgQRPviLv4wPrxRaLk7kfQntkH8kCXzTgAts8t";               //自己
            string  targetAddress = "AQye22dcXV1jCrzzC4iGbyM68LADwPSs11";                                 //别人
            string  asset         = "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"; //币种(GAS转换NNC)
            decimal sendCount     = new decimal(1);

            byte[] prikey  = Helper.GetPrivateKeyFromWIF(wif);
            byte[] pubkey  = Helper.GetPublicKeyFromPrivateKey(prikey);
            string address = Helper.GetAddressFromPublicKey(pubkey);

            SQLServer sQLServer = new SQLServer();

            sQLServer.Open();
            //接收一个读取对象
            SqlDataReader reader = sQLServer.GetUTXO(address, asset);

            //整理utxo
            Dictionary <string, List <UTXO> > dic_UTXO = GetUTXO(reader);

            sQLServer.Close();

            //拼交易
            Transaction transaction = MakeTransaction(dic_UTXO, address, targetAddress, new Hash256(asset), 0);

            transaction.version    = 0;
            transaction.attributes = new ThinNeo.Attribute[0];

            //与普通转账的区别
            transaction.type = TransactionType.InvocationTransaction;//调用合约的转账
            InvokeTransData invokeTransData = new InvokeTransData();

            byte[] script = null;
            using (ScriptBuilder sb = new ScriptBuilder()) {
                var array = new MyJson.JsonNode_Array();
                array.AddArrayValue("(addr)" + address);                                   //from
                array.AddArrayValue("(addr)" + targetAddress);                             //to
                array.AddArrayValue("(int)" + "1" + "00");                                 //value
                sb.EmitParamJson(array);                                                   //参数倒序入
                sb.EmitPushString("transfer");                                             //参数倒序入
                sb.EmitAppCall(new Hash160("0xbab964febd82c9629cc583596975f51811f25f47")); //合约
                script = sb.ToArray();
            }
            invokeTransData.script = script;
            invokeTransData.gas    = 0;
            transaction.extdata    = invokeTransData;
            ///


            byte[] msg    = transaction.GetMessage();
            string msgStr = Helper.Bytes2HexString(msg);

            byte[] signdata = Helper.Sign(msg, prikey);//签名
            transaction.AddWitness(signdata, pubkey, address);
            string txid = transaction.GetHash().ToString();

            byte[] data    = transaction.GetRawData();
            string rawdata = Helper.Bytes2HexString(data);



            //广播
            HttpRequest httpRequest = new HttpRequest();
            JObject     jObject     = httpRequest.Post("sendrawtransaction", rawdata);
            string      info        = jObject.ToString();

            Console.WriteLine("NNC" + info);
        }