private void SignAndRelay(ConsensusPayload payload) { ContractParametersContext sc; try { sc = new ContractParametersContext(payload); wallet.Sign(sc); } catch (InvalidOperationException) { return; } sc.Verifiable.Scripts = sc.GetScripts(); localNode.RelayDirectly(payload); }
private JObject SignAndRelay(Transaction tx) { ContractParametersContext context = new ContractParametersContext(tx); wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); system.Blockchain.Tell(tx); return(Utility.TransactionToJson(tx)); } else { return(context.ToJson()); } }
private static Transaction SignWithWallet(Transaction tx) { if (tx == null) { throw new ArgumentNullException("tx"); } try { tx.ToJson(); } catch (Exception) { throw new FormatException("交易格式错误"); } var wallet = new NEP6Wallet(new WalletIndexer("D:\\PrivateNet2\\node1\\Index_0001E240"), "1.json"); try { wallet.Unlock("11111111"); } catch (Exception) { Console.WriteLine("password error"); } //Signature var context = new ContractParametersContext(tx); wallet.Sign(context); if (context.Completed) { Console.WriteLine("签名成功"); tx.Witnesses = context.GetWitnesses(); } else { Console.WriteLine("签名失败"); } //Console.WriteLine(tx.ToArray().ToHexString()); Console.WriteLine("交易验证:" + tx.Verify(Blockchain.Singleton.GetSnapshot(), new List <Transaction> { tx })); Console.WriteLine(tx.ToArray().ToHexString()); return(tx); }
private JObject SendToAddress(UInt160 assetId, UInt160 scriptHash, string value) { CheckWallet(); AssetDescriptor descriptor = new AssetDescriptor(assetId); BigDecimal amount = BigDecimal.Parse(value, descriptor.Decimals); if (amount.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Transaction tx = Wallet.MakeTransaction(new[] { new TransferOutput { AssetId = assetId, Value = amount, ScriptHash = scriptHash } }); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext transContext = new ContractParametersContext(tx); Wallet.Sign(transContext); if (!transContext.Completed) { return(transContext.ToJson()); } tx.Witnesses = transContext.GetWitnesses(); if (tx.Size > 1024) { long calFee = tx.Size * 1000 + 100000; if (tx.NetworkFee < calFee) { tx.NetworkFee = calFee; } } if (tx.NetworkFee > Settings.Default.MaxFee) { throw new RpcException(-301, "The necessary fee is more than the Max_fee, this transaction is failed. Please increase your Max_fee value."); } return(SignAndRelay(tx)); }
/// <summary> /// Create an unsigned Transaction object with given parameters. /// </summary> /// <param name="script">Transaction Script</param> /// <param name="attributes">Transaction Attributes</param> /// <param name="cosigners">Transaction Cosigners</param> /// <param name="networkFee">Transaction NetworkFee, will set to estimate value(with only basic signatures) when networkFee is 0</param> /// <returns></returns> public TransactionManager MakeTransaction(byte[] script, TransactionAttribute[] attributes = null, Cosigner[] cosigners = null, long networkFee = 0) { var random = new Random(); uint height = rpcClient.GetBlockCount() - 1; Tx = new Transaction { Version = 0, Nonce = (uint)random.Next(), Script = script, Sender = sender, ValidUntilBlock = height + Transaction.MaxValidUntilBlockIncrement, Attributes = attributes ?? new TransactionAttribute[0], Cosigners = cosigners ?? new Cosigner[0], Witnesses = new Witness[0] }; RpcInvokeResult result = rpcClient.InvokeScript(script); Tx.SystemFee = Math.Max(long.Parse(result.GasConsumed) - ApplicationEngine.GasFree, 0); if (Tx.SystemFee > 0) { long d = (long)NativeContract.GAS.Factor; long remainder = Tx.SystemFee % d; if (remainder > 0) { Tx.SystemFee += d - remainder; } else if (remainder < 0) { Tx.SystemFee -= remainder; } } context = new ContractParametersContext(Tx); // set networkfee to estimate value when networkFee is 0 Tx.NetworkFee = networkFee == 0 ? EstimateNetworkFee() : networkFee; var gasBalance = new Nep5API(rpcClient).BalanceOf(NativeContract.GAS.Hash, sender); if (gasBalance >= Tx.SystemFee + Tx.NetworkFee) { return(this); } throw new InvalidOperationException($"Insufficient GAS in address: {sender.ToAddress()}"); }
private UInt256 SendTransaction(InvocationTransaction tx, Fixed8 fee) { Console.WriteLine("----------"); tx = wallet.MakeTransaction(new InvocationTransaction { Version = tx.Version, Script = tx.Script, Gas = tx.Gas, Attributes = tx.Attributes, Inputs = tx.Inputs, Outputs = tx.Outputs }, fee: fee); if (tx == null) { Console.WriteLine("Insufficient Funds"); return(null); } ContractParametersContext context; try { context = new ContractParametersContext(tx); } catch (InvalidOperationException) { Console.WriteLine("Unsynchronized Block"); return(null); } wallet.Sign(context); if (context.Completed) { context.Verifiable.Witnesses = context.GetWitnesses(); wallet.ApplyTransaction(tx); System.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); Console.WriteLine($"Relayed Transaction: {tx.ToJson()}"); return(tx.Hash); } else { Console.WriteLine(context.ToJson()); return(null); } }
public bool Sign(ContractParametersContext context) { bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { WalletAccount account = GetAccount(scriptHash); if (account?.HasKey != true) { continue; } KeyPair key = account.GetKey(); byte[] signature = context.Verifiable.Sign(key); fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); } return(fSuccess); }
private Witness PrepareDummyWitness(int maxAccounts) { var address = new WalletAccount[maxAccounts]; var wallets = new NEP6Wallet[maxAccounts]; var walletsUnlocks = new IDisposable[maxAccounts]; for (int x = 0; x < maxAccounts; x++) { wallets[x] = TestUtils.GenerateTestWallet(); walletsUnlocks[x] = wallets[x].Unlock("123"); address[x] = wallets[x].CreateAccount(); } // Generate multisignature var multiSignContract = Contract.CreateMultiSigContract(maxAccounts, address.Select(a => a.GetKey().PublicKey).ToArray()); for (int x = 0; x < maxAccounts; x++) { wallets[x].CreateAccount(multiSignContract, address[x].GetKey()); } // Sign var data = new ContractParametersContext(new Transaction() { Cosigners = new Cosigner[0], Sender = multiSignContract.ScriptHash, Attributes = new TransactionAttribute[0], NetworkFee = 0, Nonce = 0, Script = new byte[0], SystemFee = 0, ValidUntilBlock = 0, Version = 0, Witnesses = new Witness[0] }); for (int x = 0; x < maxAccounts; x++) { Assert.IsTrue(wallets[x].Sign(data)); } Assert.IsTrue(data.Completed); return(data.GetWitnesses()[0]); }
public async Task <UInt256> ExecuteAsync(Wallet wallet, UInt160 accountHash, WitnessScope witnessScope, Neo.VM.Script script, decimal additionalGas = 0) { if (disposedValue) { throw new ObjectDisposedException(nameof(OfflineNode)); } var signer = new Signer() { Account = accountHash, Scopes = witnessScope }; var tx = wallet.MakeTransaction(neoSystem.StoreView, script, accountHash, new[] { signer }); if (additionalGas > 0.0m) { tx.SystemFee += (long)additionalGas.ToBigInteger(NativeContract.GAS.Decimals); } var context = new ContractParametersContext(neoSystem.StoreView, tx, ProtocolSettings.Network); var account = wallet.GetAccount(accountHash) ?? throw new Exception(); if (account.IsMultiSigContract()) { var multiSigWallets = chain.GetMultiSigWallets(neoSystem.Settings, accountHash); for (int i = 0; i < multiSigWallets.Count; i++) { multiSigWallets[i].Sign(context); if (context.Completed) { break; } } } else { wallet.Sign(context); } if (!context.Completed) { throw new Exception(); } tx.Witnesses = context.GetWitnesses(); return(await SubmitTransactionAsync(tx).ConfigureAwait(false)); }
private Transaction SignTransaction(Transaction tx) { TR.Enter(); if (tx == null) { Console.WriteLine($"no transaction specified"); return(TR.Exit((Transaction)null)); } ContractParametersContext context; try { context = new ContractParametersContext(tx); } catch (InvalidOperationException) { Console.WriteLine($"unsynchronized block"); return(TR.Exit((Transaction)null)); } current_wallet.Sign(context); if (context.Completed) { context.Verifiable.Scripts = context.GetScripts(); current_wallet.ApplyTransaction(tx); bool relay_result = local_node.Relay(tx); if (relay_result) { return(TR.Exit(tx)); } else { Console.WriteLine($"Local Node could not relay transaction: {tx.Hash.ToString()}"); } } else { Console.WriteLine($"Incomplete Signature: {context.ToString()}"); } return(TR.Exit((Transaction)null)); }
private Transaction SignTransaction(Transaction tx) { if (tx == null) { Console.WriteLine($"no transaction specified"); return(null); } ContractParametersContext context; try { context = new ContractParametersContext(tx); } catch (InvalidOperationException) { Console.WriteLine($"unsynchronized block"); return(null); } current_wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); current_wallet.ApplyTransaction(tx); bool relay_result = system.Blockchain.Ask <RelayResultReason>(tx).Result == RelayResultReason.Succeed; if (relay_result) { return(tx); } else { Console.WriteLine($"Local Node could not relay transaction: {tx.Hash.ToString()}"); } } else { Console.WriteLine($"Incomplete Signature: {context.ToString()}"); } return(null); }
/// <summary> /// 交易签名 /// AddCode /// </summary> /// <param name="context">交易上下文</param> /// <param name="privatekey">私钥</param> /// <returns>结果</returns> public bool Sign(ContractParametersContext context, string privatekey) { bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { WalletAccount account = GetAccount(scriptHash); //if (account?.HasKey != true) continue; // 判断账号是否有nep2key 只读私有属性 只能通过构造函数赋值 所以不伪造 // 使用私钥生成钥匙 KeyPair key = new KeyPair(privatekey.HexToBytes()); byte[] signature = context.Verifiable.Sign(key); //key.PrivateKey.ToHexString(); //key.PublicKey.EncodePoint(true).ToHexString(); //File.AppendAllText("wallet.log", $"privatekey: {key.PrivateKey.ToHexString()} \n publickey: {key.PublicKey.EncodePoint(true).ToHexString()}\n"); fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); } return(fSuccess); }
private void SignAndRelay(ConsensusPayload payload) { ContractParametersContext sc; try { sc = new ContractParametersContext(payload); wallet.Sign(sc); } catch (InvalidOperationException) { return; } sc.Verifiable.Witnesses = sc.GetWitnesses(); system.LocalNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); }
public Block CreateBlock() { Contract contract = Contract.CreateMultiSigContract(M, Validators); ContractParametersContext sc = new ContractParametersContext(Block); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { if (CommitPayloads[i]?.ConsensusMessage.ViewNumber != ViewNumber) { continue; } sc.AddSignature(contract, Validators[i], CommitPayloads[i].GetDeserializedMessage <Commit>().Signature); j++; } Block.Witness = sc.GetWitnesses()[0]; Block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray(); return(Block); }
private void ProcessInvoke(JObject result) { if (Wallet != null) { Transaction tx = Wallet.MakeTransaction(result["script"].AsString().HexToBytes()); ContractParametersContext context = new ContractParametersContext(tx); Wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); } else { tx = null; } result["tx"] = tx?.ToArray().ToHexString(); } }
private JObject SignAndRelay(Transaction tx) { ContractParametersContext context = new ContractParametersContext(tx); Wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); System.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); return(tx.ToJson()); } else { return(context.ToJson()); } }
private void button9_Click_1(object sender, EventArgs e) { byte[] script; try { script = textBox6.Text.Trim().HexToBytes(); } catch (FormatException ex) { MessageBox.Show(ex.Message); return; } if (tx == null) { tx = new InvocationTransaction(); } tx.Version = 1; tx.Script = script; tx.Attributes = temp_signatures.Select(p => p.Unwrap()).ToArray(); if (tx.Inputs == null) { tx.Inputs = new CoinReference[0]; } if (tx.Outputs == null) { tx.Outputs = new TransactionOutput[0]; } if (tx.Witnesses == null) { tx.Witnesses = new Witness[0]; } try { ContractParametersContext context; context = new ContractParametersContext(tx); Clipboard.SetDataObject(context.ToString()); MessageBox.Show("Copied to clipboard"); } catch (InvalidOperationException) { MessageBox.Show(Strings.UnsynchronizedBlock); return; } }
public static Block CreateSignedBlock(Header prevHeader, IReadOnlyList <KeyPair> keyPairs, uint network, Transaction[]?transactions = null, ulong timestamp = 0) { transactions ??= Array.Empty <Transaction>(); var blockHeight = prevHeader.Index + 1; var block = new Block { Header = new Header { Version = 0, PrevHash = prevHeader.Hash, MerkleRoot = MerkleTree.ComputeRoot(transactions.Select(t => t.Hash).ToArray()), Timestamp = timestamp > prevHeader.Timestamp ? timestamp : Math.Max(Neo.Helper.ToTimestampMS(DateTime.UtcNow), prevHeader.Timestamp + 1), Index = blockHeight, PrimaryIndex = 0, NextConsensus = prevHeader.NextConsensus }, Transactions = transactions }; // generate the block header witness. Logic lifted from ConsensusContext.CreateBlock var m = keyPairs.Count - (keyPairs.Count - 1) / 3; var contract = Contract.CreateMultiSigContract(m, keyPairs.Select(k => k.PublicKey).ToList()); var signingContext = new ContractParametersContext(null, new BlockScriptHashes(prevHeader.NextConsensus), network); for (int i = 0; i < keyPairs.Count; i++) { var signature = block.Header.Sign(keyPairs[i], network); signingContext.AddSignature(contract, keyPairs[i].PublicKey, signature); if (signingContext.Completed) { break; } } if (!signingContext.Completed) { throw new Exception("block signing incomplete"); } block.Header.Witness = signingContext.GetWitnesses()[0]; return(block); }
public static void SignAndShowInformation(Transaction tx) { if (tx == null) { MessageBox.Show(Strings.InsufficientFunds); return; } ContractParametersContext context; try { context = new ContractParametersContext(tx); } catch (InvalidOperationException) { MessageBox.Show(Strings.UnsynchronizedBlock); return; } Program.CurrentWallet.Sign(context); if (context.Completed) { context.Verifiable.Scripts = context.GetScripts(); using (var ms = new System.IO.MemoryStream()) { using (var br = new System.IO.BinaryWriter(ms)) { //tx.SerializeUnsigned(br); IO.ISerializable s = tx; s.Serialize(br); } var hex = ms.ToArray().ToHexString(); System.IO.File.WriteAllText("d:\\0x00.transhex.txt", hex); } Program.CurrentWallet.ApplyTransaction(tx); Program.LocalNode.Relay(tx); InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle); } else { InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle); } }
public static void SignAndShowInformation(Transaction tx) { if (tx == null) { //MessageBox.Show(Strings.InsufficientFunds); using (WarningDlg dialog = new WarningDlg("Error", Resources.InsufficientFunds)) { if (dialog.ShowDialog() != DialogResult.OK) { } } return; } ContractParametersContext context; try { context = new ContractParametersContext(tx); } catch (InvalidOperationException) { //MessageBox.Show(Strings.UnsynchronizedBlock); using (WarningDlg dialog = new WarningDlg("Error", Resources.UnsynchronizedBlock)) { if (dialog.ShowDialog() != DialogResult.OK) { } } return; } Constant.CurrentWallet.Sign(context); if (context.Completed) { context.Verifiable.Scripts = context.GetScripts(); Constant.CurrentWallet.SaveTransaction(tx); Constant.LocalNode.Relay(tx); //InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle); } else { //InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle); } }
public Block CreateBlock() { EnsureHeader(); Contract contract = Contract.CreateMultiSigContract(M, Validators); ContractParametersContext sc = new ContractParametersContext(DBFTPlugin.System.StoreView, Block.Header); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { if (GetMessage(CommitPayloads[i])?.ViewNumber != ViewNumber) { continue; } sc.AddSignature(contract, Validators[i], GetMessage <Commit>(CommitPayloads[i]).Signature); j++; } Block.Header.Witness = sc.GetWitnesses()[0]; Block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray(); return(Block); }
private void button1_Click(object sender, EventArgs e) { if (textBox1.Text == "") { MessageBox.Show(Strings.SigningFailedNoDataMessage); return; } ContractParametersContext context = ContractParametersContext.Parse(textBox1.Text); if (!Program.CurrentWallet.Sign(context)) { MessageBox.Show(Strings.SigningFailedKeyNotFoundMessage); return; } textBox2.Text = context.ToString(); if (context.Completed) { button4.Visible = true; } }
private void button1_Click(object sender, EventArgs e) { if (textBox1.Text == "") { MessageBox.Show(LanHelper.LocalLanguage("You must input JSON object pending signature data.")); return; } ContractParametersContext context = ContractParametersContext.Parse(textBox1.Text); if (!Program.CurrentWallet.Sign(context)) { MessageBox.Show(LanHelper.LocalLanguage("The private key that can sign the data is not found.")); return; } textBox2.Text = context.ToString(); if (context.Completed) { button4.Visible = true; } }
private void SignAndRelay(ConsensusPayload payload) { ReportNeoBlockchain reportObj = new ReportNeoBlockchain("[NeoConsensusService-SignAndRelay]"); ContractParametersContext sc; try { sc = new ContractParametersContext(payload); wallet.Sign(sc); } catch (InvalidOperationException) { return; } sc.Verifiable.Scripts = sc.GetScripts(); localNode.RelayDirectly(payload); reportObj.appendElapsedTime(); }
/// <summary> /// Create an unsigned Transaction object with given parameters. /// </summary> /// <param name="script">Transaction Script</param> /// <param name="attributes">Transaction Attributes</param> /// <param name="cosigners">Transaction Cosigners</param> /// <returns></returns> public TransactionManager MakeTransaction(byte[] script, TransactionAttribute[] attributes = null, Cosigner[] cosigners = null) { var random = new Random(); uint height = rpcClient.GetBlockCount() - 1; Tx = new Transaction { Version = 0, Nonce = (uint)random.Next(), Script = script, Sender = sender, ValidUntilBlock = height + Transaction.MaxValidUntilBlockIncrement, Attributes = attributes ?? Array.Empty <TransactionAttribute>(), Cosigners = cosigners ?? Array.Empty <Cosigner>(), Witnesses = Array.Empty <Witness>() }; // Add witness hashes parameter to pass CheckWitness UInt160[] hashes = Tx.GetScriptHashesForVerifying(null); RpcInvokeResult result = rpcClient.InvokeScript(script, hashes); Tx.SystemFee = Math.Max(long.Parse(result.GasConsumed) - ApplicationEngine.GasFree, 0); if (Tx.SystemFee > 0) { long d = (long)NativeContract.GAS.Factor; long remainder = Tx.SystemFee % d; if (remainder > 0) { Tx.SystemFee += d - remainder; } else if (remainder < 0) { Tx.SystemFee -= remainder; } } context = new ContractParametersContext(Tx); signStore = new List <SignItem>(); return(this); }
private RelayResultReason SubmitInvocationTransaction(UInt160 chainHash, KeyPair keyPair, byte[] script) { ZoroSystem system = ZoroChainSystem.Singleton.GetZoroSystem(chainHash); Blockchain blockchain = ZoroChainSystem.Singleton.GetBlockchain(chainHash); InvocationTransaction tx = new InvocationTransaction { Nonce = Transaction.GetNonce(), Account = Contract.CreateSignatureRedeemScript(keyPair.PublicKey).ToScriptHash(), Script = script, GasLimit = InvocationTransaction.GetGasLimit(Fixed8.Zero), }; tx.Attributes = new TransactionAttribute[1]; tx.Attributes[0] = new TransactionAttribute(); tx.Attributes[0].Usage = TransactionAttributeUsage.Script; tx.Attributes[0].Data = tx.Account.ToArray(); ContractParametersContext context = new ContractParametersContext(tx, blockchain); Program.Wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(tx).Result; if (reason != RelayResultReason.Succeed) { Console.WriteLine($"Local Node could not relay transaction: {GetRelayResult(reason)}"); } else { Console.WriteLine($"Transaction has been accepted."); } return(reason); } return(RelayResultReason.UnableToVerify); }
public void TestCreateAccount() { var uut = new NEP6Wallet(wPath, "123", ProtocolSettings.Default); var acc = uut.CreateAccount("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632549".HexToBytes()); var tx = new Transaction() { Attributes = Array.Empty <TransactionAttribute>(), Script = new byte[1], Signers = new Signer[] { new Signer() { Account = acc.ScriptHash } }, }; var ctx = new ContractParametersContext(TestBlockchain.GetTestSnapshot(), tx, ProtocolSettings.Default.Network); var sig = uut.Sign(ctx); tx.Witnesses = ctx.GetWitnesses(); Assert.IsTrue(tx.VerifyWitnesses(ProtocolSettings.Default, TestBlockchain.GetTestSnapshot(), long.MaxValue)); Assert.ThrowsException <ArgumentNullException>(() => uut.CreateAccount((byte[])null)); Assert.ThrowsException <ArgumentException>(() => uut.CreateAccount("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551".HexToBytes())); }
public bool Sign(ContractParametersContext context) { bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { VerificationContract contract = GetContract(scriptHash); if (contract == null) { continue; } KeyPair key = GetKeyByScriptHash(scriptHash); if (key == null) { continue; } byte[] signature = context.Verifiable.Sign(key); fSuccess |= context.AddSignature(contract, key.PublicKey, signature); } return(fSuccess); }
private void ProcessInvokeWithWallet(JObject result, UInt160 sender = null, Signers signers = null) { Transaction tx = null; if (wallet != null && signers != null) { Signer[] witnessSigners = signers.GetSigners().ToArray(); UInt160[] signersAccounts = signers.GetScriptHashesForVerifying(null); if (sender != null) { if (!signersAccounts.Contains(sender)) { witnessSigners = witnessSigners.Prepend(new Signer() { Account = sender, Scopes = WitnessScope.CalledByEntry }).ToArray(); } else if (signersAccounts[0] != sender) { throw new RpcException(-32602, "The sender must be the first element of signers."); } } if (witnessSigners.Count() > 0) { tx = wallet.MakeTransaction(Convert.FromBase64String(result["script"].AsString()), sender, witnessSigners); ContractParametersContext context = new ContractParametersContext(tx); wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); } else { tx = null; } } } result["tx"] = tx?.ToArray().ToHexString(); }
private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] args, Signers signers = null) { using var snapshot = system.GetSnapshot(); var contract = NativeContract.ContractManagement.GetContract(snapshot, scriptHash); if (contract is null) { throw new RpcException(-100, "Unknown contract"); } var methodName = "verify"; Transaction tx = signers == null ? null : new Transaction { Signers = signers.GetSigners(), Attributes = Array.Empty <TransactionAttribute>() }; ContractParametersContext context = new ContractParametersContext(snapshot, tx); wallet.Sign(context); tx.Witnesses = context.Completed ? context.GetWitnesses() : null; using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: system.Settings); engine.LoadScript(new ScriptBuilder().EmitDynamicCall(scriptHash, methodName, args).ToArray(), rvcount: 1); JObject json = new JObject(); json["script"] = Convert.ToBase64String(contract.Script); json["state"] = engine.Execute(); json["gasconsumed"] = engine.GasConsumed.ToString(); json["exception"] = GetExceptionMessage(engine.FaultException); try { json["stack"] = new JArray(engine.ResultStack.Select(p => p.ToJson())); } catch (InvalidOperationException) { json["stack"] = "error: recursive reference"; } return(json); }