コード例 #1
0
        private bool CallNoInvoke(InvocationTransaction tx, out byte[] txhash)
        {
            ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx);

            bool fault = engine.State.HasFlag(VMState.FAULT);

            Fixed8 gas = engine.GasConsumed - Fixed8.FromDecimal(10);

            if (gas < Fixed8.Zero)
            {
                gas = Fixed8.Zero;
            }

            var obj = new
            {
                VMState         = engine.State.ToString(),
                GasConsumed     = (decimal)engine.GasConsumed,
                EvaluationStack = engine.ResultStack.Select(p => p.ToParameter()).ToArray(),
                GasToSpend      = (decimal)gas.Ceiling()
            };

            string res = JsonConvert.SerializeObject(obj);

            txhash = Encoding.UTF8.GetBytes(res);
            return(!fault);
        }
コード例 #2
0
        public static InvocationTransaction MakeMultiSignatureTransaction(byte[] script, int m, KeyPair[] keypairs, Fixed8 gasLimit, Fixed8 gasPrice)
        {
            InvocationTransaction tx = new InvocationTransaction
            {
                Nonce    = Transaction.GetNonce(),
                Script   = script,
                GasPrice = gasPrice,
                GasLimit = gasLimit.Ceiling(),
                Account  = GetMultiSigRedeemScriptHash(m, keypairs)
            };

            int count = keypairs.Length;

            ECPoint[] pubkeys = keypairs.Select(p => p.PublicKey).ToArray();

            tx.Attributes = new TransactionAttribute[0];

            byte[]   data       = GetHashData(tx);
            byte[][] signatures = new byte[count][];

            int i = 0;

            foreach (KeyPair keypair in keypairs.OrderBy(p => p.PublicKey))
            {
                signatures[i++] = Sign(data, keypair.PrivateKey, keypair.PublicKey);
            }

            AddWitness(tx, signatures, m, pubkeys);
            return(tx);
        }
コード例 #3
0
ファイル: ZoroHelper.cs プロジェクト: ZoroChain/Zoro-TestTool
        public static InvocationTransaction MakeTransaction(byte[] script, KeyPair keypair, Fixed8 gasLimit, Fixed8 gasPrice)
        {
            InvocationTransaction tx = new InvocationTransaction
            {
                Nonce    = Transaction.GetNonce(),
                Script   = script,
                GasPrice = gasPrice,
                GasLimit = gasLimit.Ceiling(),
                Account  = GetPublicKeyHash(keypair.PublicKey)
            };


            tx.Attributes = new TransactionAttribute[1];

            TransactionAttribute transactionAttribute = new TransactionAttribute()
            {
                Usage = TransactionAttributeUsage.Remark1,
                Data  = Encoding.UTF8.GetBytes("TestTestTest")
            };

            tx.Attributes[0] = transactionAttribute;

            byte[] data     = GetHashData(tx);
            byte[] signdata = Sign(data, keypair.PrivateKey, keypair.PublicKey);
            AddWitness(tx, signdata, keypair.PublicKey);

            return(tx);
        }
コード例 #4
0
        /// <summary>
        /// 获取GAS消耗
        /// </summary>
        /// <param name="consumed">实际消耗的gas</param>
        /// <returns>
        /// GAS消息等于实际消耗的GAS减去免费的10GAS;
        /// 若gas消耗小于等于0,则返回0;
        /// 最后对gas消耗取上整数
        /// </returns>
        public static Fixed8 GetGas(Fixed8 consumed)
        {
            Fixed8 gas = consumed - Fixed8.FromDecimal(10);

            if (gas <= Fixed8.Zero)
            {
                return(Fixed8.Zero);
            }
            return(gas.Ceiling());
        }
コード例 #5
0
        public void Ceilling_Provide100000000Fixed8Object_NoCellingNeeded()
        {
            var actual = new Fixed8(100000000);

            var cellingValue = actual.Ceiling();

            Asserting
            .That(cellingValue)
            .IsEqual(actual);
        }
コード例 #6
0
        public static Fixed8 GetGasLimit(Fixed8 consumed)
        {
            Fixed8 gas = consumed;

            if (gas <= Fixed8.Zero)
            {
                return(Fixed8.Zero);
            }
            return(gas.Ceiling());
        }
コード例 #7
0
        public static Fixed8 GetGas(Fixed8 consumed, Fixed8 freeAmount)
        {
            Fixed8 gas = consumed - freeAmount;

            if (gas <= Fixed8.Zero)
            {
                return(Fixed8.Zero);
            }
            return(gas.Ceiling());
        }
コード例 #8
0
        public static Fixed8 GetFuel(Fixed8 consumed)
        {
            Fixed8 fuel = consumed - Fixed8.FromDecimal(10);

            if (fuel <= Fixed8.Zero)
            {
                return(Fixed8.Zero);
            }
            return(fuel.Ceiling());
        }
コード例 #9
0
        public void Ceilling_Provide100500000Fixed8Object_RemaiderLessThanZeroLogic()
        {
            var actual = new Fixed8(-100500000);
            var expectedCeillingFixed8 = new Fixed8(-100000000);

            var cellingValue = actual.Ceiling();

            Asserting
            .That(cellingValue)
            .IsEqual(expectedCeillingFixed8);
        }
コード例 #10
0
        public static Fixed8 GetGas(Fixed8 consumed)
        {
            TR.Enter();
            Fixed8 gas = consumed - Fixed8.FromDecimal(10);

            if (gas <= Fixed8.Zero)
            {
                return(TR.Exit(Fixed8.Zero));
            }
            return(TR.Exit(gas.Ceiling()));
        }
コード例 #11
0
ファイル: Program.cs プロジェクト: joeqian10/BuildTransaction
        private static Fixed8 GetGasConsumed(byte[] script)
        {
            RpcInvokeResult response = rpcClient.InvokeScript(script);

            if (Fixed8.TryParse(response.GasConsumed, out Fixed8 result))
            {
                Fixed8 gas = result - Fixed8.FromDecimal(10);
                if (gas <= Fixed8.Zero)
                {
                    return(Fixed8.Zero);
                }
                else
                {
                    return(gas.Ceiling());
                }
            }
            throw new Exception();
        }
コード例 #12
0
        public static InvocationTransaction MakeTransaction(byte[] script, KeyPair keypair, Fixed8 gasLimit, Fixed8 gasPrice)
        {
            InvocationTransaction tx = new InvocationTransaction
            {
                Nonce    = Transaction.GetNonce(),
                Script   = script,
                GasPrice = gasPrice,
                GasLimit = gasLimit.Ceiling(),
                Account  = GetPublicKeyHash(keypair.PublicKey)
            };

            tx.Attributes = new TransactionAttribute[0];

            byte[] data     = GetHashData(tx);
            byte[] signdata = Sign(data, keypair.PrivateKey, keypair.PublicKey);
            AddWitness(tx, signdata, keypair.PublicKey);

            return(tx);
        }
コード例 #13
0
        public static bool Exec(Wallet wallet, LocalNode node, UInt160 scriptHash, UInt160 changeAddress, string operation, params object[] args)
        {
            byte[]            script = MakeExecScript(scriptHash, operation, args);
            ApplicationEngine engine = ApplicationEngine.Run(script);
            Fixed8            gas    = engine.GasConsumed - Fixed8.FromDecimal(10);

            if (gas < Fixed8.Zero)
            {
                gas = Fixed8.Zero;
            }
            gas = gas.Ceiling();
            Fixed8 fee = gas.Equals(Fixed8.Zero) ? Fixed8.FromDecimal(0.001m) : Fixed8.Zero;
            InvocationTransaction it = wallet.MakeTransaction(new InvocationTransaction
            {
                Version    = 1,
                Script     = script,
                Gas        = gas,
                Attributes = new TransactionAttribute[0],
                Inputs     = new CoinReference[0],
                Outputs    = new TransactionOutput[0]
            }, change_address: changeAddress, fee: fee);

            return(SignAndShowInformation(wallet, node, it));
        }
コード例 #14
0
        protected override JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "getapplicationlog":
            {
                UInt256 hash = UInt256.Parse(_params[0].AsString());
                string  path = Path.Combine(Settings.Default.Paths.ApplicationLogs, $"{hash}.json");
                return(File.Exists(path)
                            ? JObject.Parse(File.ReadAllText(path))
                            : throw new RpcException(-100, "Unknown transaction"));
            }

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

            case "listaddress":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    return(Program.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 (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UIntBase        assetId    = UIntBase.Parse(_params[0].AsString());
                    AssetDescriptor descriptor = new AssetDescriptor(assetId);
                    UInt160         from       = Wallet.ToScriptHash(_params[1].AsString());
                    UInt160         to         = Wallet.ToScriptHash(_params[2].AsString());
                    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 ? Wallet.ToScriptHash(_params[5].AsString()) : null;
                    Transaction tx             = Program.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);
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Scripts = context.GetScripts();
                        Program.Wallet.ApplyTransaction(tx);
                        LocalNode.Relay(tx);
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "sendtoaddress":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    UIntBase        assetId    = UIntBase.Parse(_params[0].AsString());
                    AssetDescriptor descriptor = new AssetDescriptor(assetId);
                    UInt160         scriptHash = Wallet.ToScriptHash(_params[1].AsString());
                    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 ? Wallet.ToScriptHash(_params[4].AsString()) : null;
                    Transaction tx             = Program.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);
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Scripts = context.GetScripts();
                        Program.Wallet.ApplyTransaction(tx);
                        LocalNode.Relay(tx);
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            case "sendmany":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    JArray to = (JArray)_params[0];
                    if (to.Count == 0)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    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 = Wallet.ToScriptHash(to[i]["address"].AsString())
                        };
                        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 ? Wallet.ToScriptHash(_params[2].AsString()) : null;
                    Transaction tx             = Program.Wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee);
                    if (tx == null)
                    {
                        throw new RpcException(-300, "Insufficient funds");
                    }
                    ContractParametersContext context = new ContractParametersContext(tx);
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        tx.Scripts = context.GetScripts();
                        Program.Wallet.ApplyTransaction(tx);
                        LocalNode.Relay(tx);
                        return(tx.ToJson());
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

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

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

            case "signdata":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    byte[]  data = System.Text.Encoding.UTF8.GetBytes(_params[0].AsString());
                    KeyPair keys = Program.Wallet.GetAccounts().First().GetKey();
                    using (keys.Decrypt())
                    {
                        byte[] pubkey = keys.PublicKey.EncodePoint(false).Skip(1).ToArray();
                        return(Convert.ToBase64String(Crypto.Default.Sign(data, keys.PrivateKey, pubkey)));
                    }
                }

            case "invoke":
            case "invokefunction":
            case "invokescript":
                JObject result = base.Process(method, _params);
                if (Program.Wallet != null)
                {
                    InvocationTransaction tx = new InvocationTransaction
                    {
                        Version = 1,
                        Script  = result["script"].AsString().HexToBytes(),
                        Gas     = Fixed8.Parse(result["gas_consumed"].AsString())
                    };
                    tx.Gas -= Fixed8.FromDecimal(10);
                    if (tx.Gas < Fixed8.Zero)
                    {
                        tx.Gas = Fixed8.Zero;
                    }
                    tx.Gas = tx.Gas.Ceiling();
                    tx     = Program.Wallet.MakeTransaction(tx);
                    if (tx != null)
                    {
                        ContractParametersContext context = new ContractParametersContext(tx);
                        Program.Wallet.Sign(context);
                        if (context.Completed)
                        {
                            tx.Scripts = context.GetScripts();
                        }
                        else
                        {
                            tx = null;
                        }
                    }
                    result["tx"] = tx?.ToArray().ToHexString();
                }
                return(result);

            case "executescript":
            {
                if (Program.Wallet == null)
                {
                    return(false);
                }
                byte[]            script = _params[0].AsString().HexToBytes();
                ApplicationEngine engine = ApplicationEngine.Run(script);
                Fixed8            gas    = engine.GasConsumed - Fixed8.FromDecimal(10);
                if (gas < Fixed8.Zero)
                {
                    gas = Fixed8.Zero;
                }
                gas = gas.Ceiling();
                Fixed8 fee = gas.Equals(Fixed8.Zero) ? Fixed8.FromDecimal(0.001m) : Fixed8.Zero;
                InvocationTransaction tx = Program.Wallet.MakeTransaction(new InvocationTransaction
                    {
                        Version    = 1,
                        Script     = script,
                        Gas        = gas,
                        Attributes = new TransactionAttribute[0],
                        Inputs     = new CoinReference[0],
                        Outputs    = new TransactionOutput[0]
                    }, fee: fee);
                if (tx == null)
                {
                    return(false);
                }
                ContractParametersContext context;
                try
                {
                    context = new ContractParametersContext(tx);
                }
                catch (Exception)
                {
                    return(false);
                }
                Program.Wallet.Sign(context);
                if (!context.Completed)
                {
                    return(false);
                }
                context.Verifiable.Scripts = context.GetScripts();
                Program.Wallet.ApplyTransaction(tx);
                return(LocalNode.Relay(tx));
            }

            default:
                return(base.Process(method, _params));
            }
        }