public override bool Match(ApplicationEngine engine) { return(engine.CallingScriptHash is null || engine.CallingScriptHash == engine.EntryScriptHash); }
public void System_Runtime_GetInvocationCounter() { ContractState contractA, contractB, contractC; var snapshot = TestBlockchain.GetStore().GetSnapshot(); var contracts = (TestDataCache <UInt160, ContractState>)snapshot.Contracts; // Create dummy contracts using (var script = new ScriptBuilder()) { script.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); contractA = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(script.ToArray()).ToArray() }; contractB = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; contractC = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; // Init A,B,C contracts // First two drops is for drop method and arguments contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractA.ScriptHash.ToArray())); contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractB.ScriptHash.ToArray())); contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractC.ScriptHash.ToArray())); contracts.Add(contractA.ScriptHash, contractA); contracts.Add(contractB.ScriptHash, contractB); contracts.Add(contractC.ScriptHash, contractC); } // Call A,B,B,C using (var script = new ScriptBuilder()) { script.EmitSysCall(InteropService.System_Contract_Call, contractA.ScriptHash.ToArray(), "dummyMain", 0); script.EmitSysCall(InteropService.System_Contract_Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); script.EmitSysCall(InteropService.System_Contract_Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); script.EmitSysCall(InteropService.System_Contract_Call, contractC.ScriptHash.ToArray(), "dummyMain", 0); // Execute var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); // Check the results CollectionAssert.AreEqual ( engine.ResultStack.Select(u => (int)((VM.Types.Integer)u).GetBigInteger()).ToArray(), new int[] { 1, /* A */ 1, /* B */ 2, /* B */ 1 /* C */ } ); } }
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 { AssetId = k.AssetId, Value = g.Aggregate(BigInteger.Zero, (x, y) => x + y.Value.Value), Account = k.Account }).ToArray(); Transaction tx; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); if (cOutputs.Length == 0) { tx = new ContractTransaction(); } else { UInt160[] addresses = Program.CurrentWallet.GetAccounts().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 = engine.EvaluationStack.Pop().GetArray().Reverse().Zip(addresses, (i, a) => new { Account = a, Value = i.GetBigInteger() }).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(); if (tx is ContractTransaction ctx) { tx = Program.CurrentWallet.MakeTransaction(ctx, change_address: ChangeAddress, fee: Fee); } return(tx); }
internal override ContractTask Initialize(ApplicationEngine engine) { engine.Snapshot.Add(CreateStorageKey(Prefix_MinimumDeploymentFee), new StorageItem(10_00000000)); engine.Snapshot.Add(CreateStorageKey(Prefix_NextAvailableId), new StorageItem(1)); return(ContractTask.CompletedTask); }
public override bool Match(ApplicationEngine engine) { return(!Expression.Match(engine)); }
private void Persist(Block block) { using (Snapshot snapshot = GetSnapshot()) { List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); snapshot.PersistingBlock = block; if (block.Index > 0) { NativeContract[] contracts = { NativeContract.GAS, NativeContract.NEO }; using (ApplicationEngine engine = new ApplicationEngine(TriggerType.System, null, snapshot, 0, true)) { using (ScriptBuilder sb = new ScriptBuilder()) { foreach (NativeContract contract in contracts) { sb.EmitAppCall(contract.Hash, "onPersist"); } engine.LoadScript(sb.ToArray()); } if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.Blocks.Add(block.Hash, block.Trim()); foreach (Transaction tx in block.Transactions) { snapshot.Transactions.Add(tx.Hash, new TransactionState { BlockIndex = block.Index, Transaction = tx }); using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, snapshot.Clone(), tx.Gas)) { engine.LoadScript(tx.Script); if (!engine.Execute().HasFlag(VMState.FAULT)) { engine.Snapshot.Commit(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.BlockHashIndex.GetAndChange().Hash = block.Hash; snapshot.BlockHashIndex.GetAndChange().Index = block.Index; if (block.Index == header_index.Count) { header_index.Add(block.Hash); snapshot.HeaderHashIndex.GetAndChange().Hash = block.Hash; snapshot.HeaderHashIndex.GetAndChange().Index = block.Index; } foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } } UpdateCurrentSnapshot(); OnPersistCompleted(block); }
private ContractTask <ContractState> Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest) { return(Deploy(engine, nefFile, manifest, StackItem.Null)); }
public void TestRuntime_Platform() { ApplicationEngine.GetPlatform().Should().Be("NEO"); }
public void Runtime_GetNotifications_Test() { UInt160 scriptHash2; var snapshot = TestBlockchain.GetTestSnapshot(); 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.DeleteContract(scriptHash2); snapshot.AddContract(scriptHash2, TestUtils.GetContract(script.ToArray(), TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer))); } // Wrong length using (var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot)) 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 = ApplicationEngine.Create(TriggerType.Application, null, snapshot)) 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.EmitDynamicCall(scriptHash2, "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()); engine.CurrentContext.GetState <ExecutionContextState>().Contract = new(); 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 = ApplicationEngine.Create(TriggerType.Application, null, snapshot)) 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.EmitDynamicCall(scriptHash2, "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()); engine.CurrentContext.GetState <ExecutionContextState>().Contract = new(); 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.DeleteContract(scriptHash2); }
private StackItem GetFeePerByte(ApplicationEngine engine, VMArray args) { return(GetFeePerByte(engine.Snapshot)); }
private StackItem GetBlockedAccounts(ApplicationEngine engine, VMArray args) { return(GetBlockedAccounts(engine.Snapshot).Select(p => (StackItem)p.ToArray()).ToList()); }
private StackItem GetMaxTransactionsPerBlock(ApplicationEngine engine, VMArray args) { return(GetMaxTransactionsPerBlock(engine.Snapshot)); }
internal override ContractTask Initialize(ApplicationEngine engine) { UInt160 account = Contract.GetBFTAddress(engine.ProtocolSettings.StandbyValidators); return Mint(engine, account, 30_000_000 * Factor, false); }
public void System_Blockchain_GetBlock() { var tx = new Transaction() { Script = new byte[] { 0x01 }, Attributes = Array.Empty <TransactionAttribute>(), NetworkFee = 0x02, SystemFee = 0x03, Nonce = 0x04, ValidUntilBlock = 0x05, Version = 0x06, Witnesses = new Witness[] { new Witness() { VerificationScript = new byte[] { 0x07 } } }, Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), }; var block = new Block() { Index = 0, Timestamp = 2, Version = 3, Witness = new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] }, PrevHash = UInt256.Zero, MerkleRoot = UInt256.Zero, NextConsensus = UInt160.Zero, ConsensusData = new ConsensusData() { Nonce = 1, PrimaryIndex = 1 }, Transactions = new Transaction[] { tx } }; var snapshot = Blockchain.Singleton.GetSnapshot(); using (var script = new ScriptBuilder()) { script.EmitPush(block.Hash.ToArray()); script.EmitSysCall(ApplicationEngine.System_Blockchain_GetBlock); // Without block var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Peek().IsNull); // Not traceable block var height = snapshot.BlockHashIndex.GetAndChange(); height.Index = block.Index + Transaction.MaxValidUntilBlockIncrement; var blocks = snapshot.Blocks; var txs = snapshot.Transactions; blocks.Add(block.Hash, block.Trim()); txs.Add(tx.Hash, new TransactionState() { Transaction = tx, BlockIndex = block.Index, VMState = VMState.HALT }); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Peek().IsNull); // With block height.Index = block.Index; script.EmitSysCall(ApplicationEngine.System_Json_Serialize); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(ByteString)); Assert.AreEqual(engine.ResultStack.Pop().GetSpan().ToHexString(), "5b2261564e62466b35384f51717547373870747154766561762f48677941566a72634e41434d4e59705c7530303242366f6f3d222c332c22414141414141414141414141414141414141414141414141414141414141414141414141414141414141413d222c22414141414141414141414141414141414141414141414141414141414141414141414141414141414141413d222c322c302c224141414141414141414141414141414141414141414141414141413d222c315d"); Assert.AreEqual(0, engine.ResultStack.Count); // Clean blocks.Delete(block.Hash); txs.Delete(tx.Hash); } }
private void Persist(Block block) { using (SnapshotCache snapshot = system.GetSnapshot()) { List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, block)) { engine.LoadScript(onPersistScript); if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } DataCache clonedSnapshot = snapshot.CreateSnapshot(); // Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead. foreach (Transaction tx in block.Transactions) { using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, clonedSnapshot, block, tx.SystemFee)) { engine.LoadScript(tx.Script); if (engine.Execute() == VMState.HALT) { clonedSnapshot.Commit(); } else { clonedSnapshot = snapshot.CreateSnapshot(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.PostPersist, null, snapshot, block)) { engine.LoadScript(postPersistScript); if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(block, snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(block, snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } system.MemPool.UpdatePoolForBlockPersisted(block, snapshot); } extensibleWitnessWhiteList = null; block_cache.Remove(block.PrevHash); Context.System.EventStream.Publish(new PersistCompleted { Block = block }); if (system.HeaderCache.TryRemoveFirst(out Header header)) { Debug.Assert(header.Index == block.Index); } }
public override bool Match(ApplicationEngine engine) { return(Expressions.Any(p => p.Match(engine))); }
public new StackItem TotalSupply(ApplicationEngine engine, VM.Types.Array args) { return(base.TotalSupply(engine, args)); }
private void Persist(Block block) { WriteBatch batch = new WriteBatch(); DbCache <UInt160, AccountState> accounts = new DbCache <UInt160, AccountState>(db, DataEntryPrefix.ST_Account, batch); DbCache <UInt256, UnspentCoinState> unspentcoins = new DbCache <UInt256, UnspentCoinState>(db, DataEntryPrefix.ST_Coin, batch); DbCache <UInt256, SpentCoinState> spentcoins = new DbCache <UInt256, SpentCoinState>(db, DataEntryPrefix.ST_SpentCoin, batch); DbCache <ECPoint, ValidatorState> validators = new DbCache <ECPoint, ValidatorState>(db, DataEntryPrefix.ST_Validator, batch); DbCache <UInt256, AssetState> assets = new DbCache <UInt256, AssetState>(db, DataEntryPrefix.ST_Asset, batch); DbCache <UInt160, ContractState> contracts = new DbCache <UInt160, ContractState>(db, DataEntryPrefix.ST_Contract, batch); DbCache <StorageKey, StorageItem> storages = new DbCache <StorageKey, StorageItem>(db, DataEntryPrefix.ST_Storage, batch); DbMetaDataCache <ValidatorsCountState> validators_count = new DbMetaDataCache <ValidatorsCountState>(db, DataEntryPrefix.IX_ValidatorsCount); long amount_sysfee = GetSysFeeAmount(block.PrevHash) + (long)block.Transactions.Sum(p => p.SystemFee); batch.Put(SliceBuilder.Begin(DataEntryPrefix.DATA_Block).Add(block.Hash), SliceBuilder.Begin().Add(amount_sysfee).Add(block.Trim())); foreach (Transaction tx in block.Transactions) { batch.Put(SliceBuilder.Begin(DataEntryPrefix.DATA_Transaction).Add(tx.Hash), SliceBuilder.Begin().Add(block.Index).Add(tx.ToArray())); unspentcoins.Add(tx.Hash, new UnspentCoinState { Items = Enumerable.Repeat(CoinState.Confirmed, tx.Outputs.Length).ToArray() }); foreach (TransactionOutput output in tx.Outputs) { AccountState account = accounts.GetAndChange(output.ScriptHash, () => new AccountState(output.ScriptHash)); if (account.Balances.ContainsKey(output.AssetId)) { account.Balances[output.AssetId] += output.Value; } else { account.Balances[output.AssetId] = output.Value; } if (output.AssetId.Equals(GoverningToken.Hash) && account.Votes.Length > 0) { foreach (ECPoint pubkey in account.Votes) { validators.GetAndChange(pubkey, () => new ValidatorState(pubkey)).Votes += output.Value; } validators_count.GetAndChange().Votes[account.Votes.Length - 1] += output.Value; } } foreach (var group in tx.Inputs.GroupBy(p => p.PrevHash)) { Transaction tx_prev = GetTransaction(ReadOptions.Default, group.Key, out int height); foreach (CoinReference input in group) { unspentcoins.GetAndChange(input.PrevHash).Items[input.PrevIndex] |= CoinState.Spent; TransactionOutput out_prev = tx_prev.Outputs[input.PrevIndex]; AccountState account = accounts.GetAndChange(out_prev.ScriptHash); if (out_prev.AssetId.Equals(GoverningToken.Hash)) { spentcoins.GetAndChange(input.PrevHash, () => new SpentCoinState { TransactionHash = input.PrevHash, TransactionHeight = (uint)height, Items = new Dictionary <ushort, uint>() }).Items.Add(input.PrevIndex, block.Index); if (account.Votes.Length > 0) { foreach (ECPoint pubkey in account.Votes) { ValidatorState validator = validators.GetAndChange(pubkey); validator.Votes -= out_prev.Value; if (!validator.Registered && validator.Votes.Equals(Fixed8.Zero)) { validators.Delete(pubkey); } } validators_count.GetAndChange().Votes[account.Votes.Length - 1] -= out_prev.Value; } } account.Balances[out_prev.AssetId] -= out_prev.Value; } } switch (tx) { #pragma warning disable CS0612 case RegisterTransaction tx_register: assets.Add(tx.Hash, new AssetState { AssetId = tx_register.Hash, AssetType = tx_register.AssetType, Name = tx_register.Name, Amount = tx_register.Amount, Available = Fixed8.Zero, Precision = tx_register.Precision, Fee = Fixed8.Zero, FeeAddress = new UInt160(), Owner = tx_register.Owner, Admin = tx_register.Admin, Issuer = tx_register.Admin, Expiration = block.Index + 2 * 2000000, IsFrozen = false }); break; #pragma warning restore CS0612 case IssueTransaction _: foreach (TransactionResult result in tx.GetTransactionResults().Where(p => p.Amount < Fixed8.Zero)) { assets.GetAndChange(result.AssetId).Available -= result.Amount; } break; case ClaimTransaction _: foreach (CoinReference input in ((ClaimTransaction)tx).Claims) { if (spentcoins.TryGet(input.PrevHash)?.Items.Remove(input.PrevIndex) == true) { spentcoins.GetAndChange(input.PrevHash); } } break; #pragma warning disable CS0612 case EnrollmentTransaction tx_enrollment: validators.GetAndChange(tx_enrollment.PublicKey, () => new ValidatorState(tx_enrollment.PublicKey)).Registered = true; break; #pragma warning restore CS0612 case StateTransaction tx_state: foreach (StateDescriptor descriptor in tx_state.Descriptors) { switch (descriptor.Type) { case StateType.Account: ProcessAccountStateDescriptor(descriptor, accounts, validators, validators_count); break; case StateType.Validator: ProcessValidatorStateDescriptor(descriptor, validators); break; } } break; #pragma warning disable CS0612 case PublishTransaction tx_publish: contracts.GetOrAdd(tx_publish.ScriptHash, () => new ContractState { Script = tx_publish.Script, ParameterList = tx_publish.ParameterList, ReturnType = tx_publish.ReturnType, ContractProperties = (ContractPropertyState)Convert.ToByte(tx_publish.NeedStorage), Name = tx_publish.Name, CodeVersion = tx_publish.CodeVersion, Author = tx_publish.Author, Email = tx_publish.Email, Description = tx_publish.Description }); break; #pragma warning restore CS0612 case InvocationTransaction tx_invocation: CachedScriptTable script_table = new CachedScriptTable(contracts); using (StateMachine service = new StateMachine(block, accounts, assets, contracts, storages)) { ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx_invocation, script_table, service, tx_invocation.Gas); engine.LoadScript(tx_invocation.Script, false); if (engine.Execute()) { service.Commit(); } ApplicationExecuted?.Invoke(this, new ApplicationExecutedEventArgs(tx_invocation, service.Notifications.ToArray(), engine)); } break; } } accounts.DeleteWhere((k, v) => !v.IsFrozen && v.Votes.Length == 0 && v.Balances.All(p => p.Value <= Fixed8.Zero)); accounts.Commit(); unspentcoins.DeleteWhere((k, v) => v.Items.All(p => p.HasFlag(CoinState.Spent))); unspentcoins.Commit(); spentcoins.DeleteWhere((k, v) => v.Items.Count == 0); spentcoins.Commit(); validators.Commit(); assets.Commit(); contracts.Commit(); storages.Commit(); validators_count.Commit(batch); batch.Put(SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock), SliceBuilder.Begin().Add(block.Hash).Add(block.Index)); db.Write(WriteOptions.Default, batch); current_block_height = block.Index; }
public StackItem TestOnPersist(ApplicationEngine engine, VMArray args) { return(OnPersist(engine, args)); }
protected virtual bool OnPersist(ApplicationEngine engine) { return(true); }
private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] manifest) { return(Update(engine, nefFile, manifest, StackItem.Null)); }
protected StackItem SupportedStandardsMethod(ApplicationEngine engine, VMArray args) { return(SupportedStandards.Select(p => (StackItem)p).ToList()); }
public async Task Run() { _logger.LogInfo <KeepAliveTask>(null, "Starting a keep alive request"); await _requestProvider.GetStringAsync(ApplicationEngine.RouteUrl(RouteNames.KeepAlive, null, true)); }
protected void SetBreadcrumbToRoute(string displayText, string routeName, object routeParams = null, string description = null, bool localize = true) { SetBreadcrumbToUrl(displayText, ApplicationEngine.RouteUrl(routeName, routeParams, true), description, localize); }
public void System_Blockchain_GetBlock() { var tx = new Transaction() { Script = new byte[] { 0x01 }, Attributes = new TransactionAttribute[0], Cosigners = new Cosigner[0], NetworkFee = 0x02, SystemFee = 0x03, Nonce = 0x04, ValidUntilBlock = 0x05, Version = 0x06, Witnesses = new Witness[] { new Witness() { VerificationScript = new byte[] { 0x07 } } }, Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), }; var block = new Block() { Index = 1, Timestamp = 2, Version = 3, Witness = new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] }, PrevHash = UInt256.Zero, MerkleRoot = UInt256.Zero, NextConsensus = UInt160.Zero, ConsensusData = new ConsensusData() { Nonce = 1, PrimaryIndex = 1 }, Transactions = new Transaction[] { tx } }; var snapshot = TestBlockchain.GetStore().GetSnapshot(); using (var script = new ScriptBuilder()) { script.EmitPush(block.Hash.ToArray()); script.EmitSysCall(InteropService.System_Blockchain_GetBlock); // Without block var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Peek().IsNull); // With block var blocks = (TestDataCache <UInt256, TrimmedBlock>)snapshot.Blocks; var txs = (TestDataCache <UInt256, TransactionState>)snapshot.Transactions; blocks.Add(block.Hash, block.Trim()); txs.Add(tx.Hash, new TransactionState() { Transaction = tx, BlockIndex = block.Index, VMState = VMState.HALT }); script.EmitSysCall(InteropService.Neo_Json_Serialize); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(ByteArray)); Assert.AreEqual(engine.ResultStack.Pop().GetByteArray().ToHexString(), "5b22515c7546464644795c75464646445c75464646445c75303030335c75464646445c75464646445c754646464475465c7530303046715c75303132415c625b595c75303434335c75464646445c75464646447d5d767b385c7546464644785c75303032375c75464646445c7546464644222c332c225c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c7530303030222c225c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c7530303030222c322c312c225c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c7530303030222c315d"); Assert.AreEqual(0, engine.ResultStack.Count); // Clean blocks.Delete(block.Hash); txs.Delete(tx.Hash); } }
public void MemorySearch() { var snapshot = TestBlockchain.GetTestSnapshot(); using (var script = new ScriptBuilder()) { script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 0); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 1); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 2); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 3); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "d", 0); using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheVauthSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(5, engine.ResultStack.Count); Assert.AreEqual(-1, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(-1, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(2, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(2, engine.ResultStack.Pop <Integer>().GetInteger()); } using (var script = new ScriptBuilder()) { script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 0, false); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 1, false); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 2, false); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 3, false); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "d", 0, false); using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheVauthSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(5, engine.ResultStack.Count); Assert.AreEqual(-1, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(-1, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(2, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(2, engine.ResultStack.Pop <Integer>().GetInteger()); } using (var script = new ScriptBuilder()) { script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 0, true); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 1, true); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 2, true); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "c", 3, true); script.EmitDynamicCall(NativeContract.StdLib.Hash, "memorySearch", "abc", "d", 0, true); using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheVauthSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(5, engine.ResultStack.Count); Assert.AreEqual(-1, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(2, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(-1, engine.ResultStack.Pop <Integer>().GetInteger()); Assert.AreEqual(-1, engine.ResultStack.Pop <Integer>().GetInteger()); } }
public Transaction MakeTransaction(List <TransactionAttribute> attributes, IEnumerable <TransferOutput> outputs, UInt160 from = 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) { byte[] script; using (ScriptBuilder sb2 = new ScriptBuilder()) { foreach (UInt160 account in accounts) { sb2.EmitAppCall(output.AssetId, "balanceOf", account); } sb2.Emit(OpCode.DEPTH, OpCode.PACK); script = sb2.ToArray(); } ApplicationEngine engine = ApplicationEngine.Run(script); if (engine.State.HasFlag(VMState.FAULT)) { return(null); } var balances = ((IEnumerable <StackItem>)(VMArray) engine.EvaluationStack.Pop()).Reverse().Zip(accounts, (i, a) => new { Account = a, Value = i.GetBigInteger() }).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); } } 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.Scripts = 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 = MakeTransaction(tx, from, change_address, fee); return(tx); }
public void Runtime_GetNotifications_Test() { UInt160 scriptHash2; var snapshot = TestBlockchain.GetStore().GetSnapshot(); using (var script = new ScriptBuilder()) { // Drop arguments script.Emit(VM.OpCode.TOALTSTACK); script.Emit(VM.OpCode.DROP); script.Emit(VM.OpCode.FROMALTSTACK); // Notify method script.EmitSysCall(InteropService.System_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.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 1 -> 13 script.EmitPush(13); script.EmitSysCall(InteropService.System_Runtime_Notify); // Call script script.EmitAppCall(scriptHash2, "test"); // Drop return script.Emit(OpCode.DROP); // Receive all notifications script.EmitPush(new byte[0]); script.EmitSysCall(InteropService.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, "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.System_Runtime_Notify); // Call script script.EmitAppCall(scriptHash2, "test"); // Drop return script.Emit(OpCode.DROP); // Receive all notifications script.EmitPush(scriptHash2.ToArray()); script.EmitSysCall(InteropService.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, "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); }
protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount) { if (engine.Service.Trigger != TriggerType.Application) { throw new InvalidOperationException(); } if (amount.Sign < 0) { throw new ArgumentOutOfRangeException(nameof(amount)); } if (!from.Equals(new UInt160(engine.CurrentContext.CallingScriptHash)) && !engine.Service.CheckWitness(engine, from)) { return(false); } ContractState contract_to = engine.Service.Snapshot.Contracts.TryGet(to); if (contract_to?.Payable == false) { return(false); } StorageKey key_from = CreateAccountKey(from); StorageItem storage_from = engine.Service.Snapshot.Storages.TryGet(key_from); if (amount.IsZero) { if (storage_from != null) { TState state_from = new TState(); state_from.FromByteArray(storage_from.Value); OnBalanceChanging(engine, from, state_from, amount); } } else { if (storage_from is null) { return(false); } TState state_from = new TState(); state_from.FromByteArray(storage_from.Value); if (state_from.Balance < amount) { return(false); } if (from.Equals(to)) { OnBalanceChanging(engine, from, state_from, BigInteger.Zero); } else { OnBalanceChanging(engine, from, state_from, -amount); if (state_from.Balance == amount) { engine.Service.Snapshot.Storages.Delete(key_from); } else { state_from.Balance -= amount; storage_from = engine.Service.Snapshot.Storages.GetAndChange(key_from); storage_from.Value = state_from.ToByteArray(); } StorageKey key_to = CreateAccountKey(to); StorageItem storage_to = engine.Service.Snapshot.Storages.GetAndChange(key_to, () => new StorageItem { Value = new TState().ToByteArray() }); TState state_to = new TState(); state_to.FromByteArray(storage_to.Value); OnBalanceChanging(engine, to, state_to, amount); state_to.Balance += amount; storage_to.Value = state_to.ToByteArray(); } } engine.Service.SendNotification(engine, ScriptHash, new StackItem[] { "Transfer", from.ToArray(), to.ToArray(), amount }); return(true); }
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 { var addyFrom = comboBoxFrom.SelectedItem.ToString(); UInt160[] addresses = !string.IsNullOrEmpty(addyFrom)? new UInt160[] { addyFrom.ToScriptHash() } : Program.CurrentWallet.GetAccounts().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(); } using (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); }