/// <summary> /// Initializes a new instance of the <see cref="NotifyEventArgs"/> class. /// </summary> /// <param name="container">The container that containing the executed script.</param> /// <param name="script_hash">The script hash of the contract that sends the log.</param> /// <param name="eventName">The name of the event.</param> /// <param name="state">The arguments of the event.</param> public NotifyEventArgs(IVerifiable container, UInt160 script_hash, string eventName, Array state) { this.ScriptContainer = container; this.ScriptHash = script_hash; this.EventName = eventName; this.State = state; }
/// <summary> /// Sends a notification for the specified contract. /// </summary> /// <param name="hash">The hash of the specified contract.</param> /// <param name="eventName">The name of the event.</param> /// <param name="state">The arguments of the event.</param> protected internal void SendNotification(UInt160 hash, string eventName, Array state) { NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy()); Notify?.Invoke(this, notification); notifications ??= new List<NotifyEventArgs>(); notifications.Add(notification); }
public virtual void FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; Name = @struct[0].GetString(); Parameters = ((Array)@struct[1]).Select(p => p.ToInteroperable <ContractParameterDefinition>()).ToArray(); }
/// <summary> /// The implementation of System.Contract.NativePostPersist. /// Calls to the <see cref="NativeContract.PostPersist"/> of all native contracts. /// </summary> protected internal async void NativePostPersist() { try { if (Trigger != TriggerType.PostPersist) { throw new InvalidOperationException(); } foreach (NativeContract contract in NativeContract.Contracts) { uint[] updates = ProtocolSettings.NativeUpdateHistory[contract.Name]; if (updates.Length == 0) { continue; } if (updates[0] <= PersistingBlock.Index) { await contract.PostPersist(this); } } } catch (Exception ex) { Throw(ex); } }
/// <summary> /// The implementation of System.Runtime.Notify. /// Sends a notification. /// </summary> /// <param name="eventName">The name of the event.</param> /// <param name="state">The arguments of the event.</param> protected internal void RuntimeNotify(byte[] eventName, Array state) { if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize); SendNotification(CurrentScriptHash, Utility.StrictUTF8.GetString(eventName), state); }
/// <summary> /// The implementation of System.Runtime.GetNotifications. /// Gets the notifications sent by the specified contract during the execution. /// </summary> /// <param name="hash">The hash of the specified contract. It can be set to <see langword="null"/> to get all notifications.</param> /// <returns>The notifications sent during the execution.</returns> protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) { IEnumerable<NotifyEventArgs> notifications = Notifications; if (hash != null) // must filter by scriptHash notifications = notifications.Where(p => p.ScriptHash == hash); NotifyEventArgs[] array = notifications.ToArray(); if (array.Length > Limits.MaxStackSize) throw new InvalidOperationException(); return array; }
/// <summary> /// The implementation of System.Runtime.CheckWitness. /// Determines whether the specified account has witnessed the current transaction. /// </summary> /// <param name="hashOrPubkey">The hash or public key of the account.</param> /// <returns><see langword="true"/> if the account has witnessed the current transaction; otherwise, <see langword="false"/>.</returns> protected internal bool CheckWitness(byte[] hashOrPubkey) { UInt160 hash = hashOrPubkey.Length switch { 20 => new UInt160(hashOrPubkey), 33 => Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(hashOrPubkey, ECCurve.Secp256r1)).ToScriptHash(), _ => throw new ArgumentException(null, nameof(hashOrPubkey)) }; return CheckWitnessInternal(hash); }
void IInteroperable.FromStackItem(StackItem stackItem) { Array array = (Array)stackItem; Id = (int)array[0].GetInteger(); UpdateCounter = (ushort)array[1].GetInteger(); Hash = new UInt160(array[2].GetSpan()); Nef = array[3].GetSpan().AsSerializable <NefFile>(); Manifest = array[4].ToInteroperable <ContractManifest>(); }
public void FromStackItem(StackItem stackItem) { Array array = (Array)stackItem; OriginalTxid = new UInt256(array[0].GetSpan()); ValtForResponse = (long)array[1].GetInteger(); Url = array[2].GetString(); Filter = array[3].GetString(); CallbackContract = new UInt160(array[4].GetSpan()); CallbackMethod = array[5].GetString(); UserData = array[6].GetSpan().ToArray(); }
/// <summary> /// Converts the event from a JSON object. /// </summary> /// <param name="json">The event represented by a JSON object.</param> /// <returns>The converted event.</returns> public static ContractEventDescriptor FromJson(JObject json) { ContractEventDescriptor descriptor = new() { Name = json["name"].GetString(), Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson(u)).ToArray(), }; if (string.IsNullOrEmpty(descriptor.Name)) { throw new FormatException(); } _ = descriptor.Parameters.ToDictionary(p => p.Name); return(descriptor); }
/// <summary> /// The implementation of System.Contract.CallNative. /// Calls to a native contract. /// </summary> /// <param name="version">The version of the native contract to be called.</param> protected internal void CallNativeContract(byte version) { NativeContract contract = NativeContract.GetContract(CurrentScriptHash); if (contract is null) { throw new InvalidOperationException("It is not allowed to use \"System.Contract.CallNative\" directly."); } uint[] updates = ProtocolSettings.NativeUpdateHistory[contract.Name]; if (updates.Length == 0) { throw new InvalidOperationException($"The native contract {contract.Name} is not active."); } if (updates[0] > NativeContract.Ledger.CurrentIndex(Snapshot)) { throw new InvalidOperationException($"The native contract {contract.Name} is not active."); } contract.Invoke(this, version); }
void IInteroperable.FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; Name = @struct[0].GetString(); Groups = ((Array)@struct[1]).Select(p => p.ToInteroperable <ContractGroup>()).ToArray(); if (((Map)@struct[2]).Count != 0) { throw new ArgumentException(null, nameof(stackItem)); } SupportedStandards = ((Array)@struct[3]).Select(p => p.GetString()).ToArray(); Abi = @struct[4].ToInteroperable <ContractAbi>(); Permissions = ((Array)@struct[5]).Select(p => p.ToInteroperable <ContractPermission>()).ToArray(); Trusts = @struct[6] switch { Null => WildcardContainer <ContractPermissionDescriptor> .CreateWildcard(), Array array => WildcardContainer <ContractPermissionDescriptor> .Create(array.Select(p => new ContractPermissionDescriptor(p.GetSpan())).ToArray()), _ => throw new ArgumentException(null, nameof(stackItem)) }; Extra = JObject.Parse(@struct[7].GetSpan()); }
/// <summary> /// The implementation of System.Runtime.Log. /// Writes a log. /// </summary> /// <param name="state">The message of the log.</param> protected internal void RuntimeLog(byte[] state) { if (state.Length > MaxNotificationSize) throw new ArgumentException(null, nameof(state)); string message = Utility.StrictUTF8.GetString(state); Log?.Invoke(this, new LogEventArgs(ScriptContainer, CurrentScriptHash, message)); }
/// <summary> /// Deserializes a <see cref="StackItem"/> from byte array. /// </summary> /// <param name="data">The byte array to parse.</param> /// <param name="maxArraySize">The maximum length of arrays during the deserialization.</param> /// <param name="referenceCounter">The <see cref="ReferenceCounter"/> used by the <see cref="StackItem"/>.</param> /// <returns>The deserialized <see cref="StackItem"/>.</returns> public static StackItem Deserialize(byte[] data, uint maxArraySize, ReferenceCounter referenceCounter = null) { using MemoryStream ms = new(data, false); using BinaryReader reader = new(ms, Utility.StrictUTF8, true); return(Deserialize(reader, maxArraySize, (uint)data.Length, referenceCounter)); }
/// <summary> /// The implementation of System.Contract.Call. /// Use it to call another contract dynamically. /// </summary> /// <param name="contractHash">The hash of the contract to be called.</param> /// <param name="method">The method of the contract to be called.</param> /// <param name="callFlags">The <see cref="CallFlags"/> to be used to call the contract.</param> /// <param name="args">The arguments to be used.</param> protected internal void CallContract(UInt160 contractHash, string method, CallFlags callFlags, Array args) { if (method.StartsWith('_')) { throw new ArgumentException($"Invalid Method Name: {method}"); } if ((callFlags & ~CallFlags.All) != 0) { throw new ArgumentOutOfRangeException(nameof(callFlags)); } ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) { throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); } ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Count); if (md is null) { throw new InvalidOperationException($"Method \"{method}\" with {args.Count} parameter(s) doesn't exist in the contract {contractHash}."); } bool hasReturnValue = md.ReturnType != ContractParameterType.Void; if (!hasReturnValue) { CurrentContext.EvaluationStack.Push(StackItem.Null); } CallContractInternal(contract, md, callFlags, hasReturnValue, args); }
/// <summary> /// The implementation of System.Contract.CreateMultisigAccount. /// Calculates corresponding multisig account scripthash for the given public keys. /// </summary> /// <param name="m">The minimum number of correct signatures that need to be provided in order for the verification to pass.</param> /// <param name="pubKeys">The public keys of the account.</param> /// <returns>The hash of the account.</returns> internal protected static UInt160 CreateMultisigAccount(int m, ECPoint[] pubKeys) { return(Contract.CreateMultiSigRedeemScript(m, pubKeys).ToScriptHash()); }