Beispiel #1
0
        protected NativeContract()
        {
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitPush(Name);
                sb.EmitSysCall(ApplicationEngine.Neo_Native_Call);
                this.Script = sb.ToArray();
            }
            this.Hash = Script.ToScriptHash();
            List <ContractMethodDescriptor> descriptors = new List <ContractMethodDescriptor>();
            List <string> safeMethods = new List <string>();

            foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                ContractMethodAttribute attribute = member.GetCustomAttribute <ContractMethodAttribute>();
                if (attribute is null)
                {
                    continue;
                }
                ContractMethodMetadata metadata = new ContractMethodMetadata(member, attribute);
                descriptors.Add(new ContractMethodDescriptor
                {
                    Name       = metadata.Name,
                    ReturnType = ToParameterType(metadata.Handler.ReturnType),
                    Parameters = metadata.Parameters.Select(p => new ContractParameterDefinition {
                        Type = ToParameterType(p.Type), Name = p.Name
                    }).ToArray()
                });
                if (!attribute.RequiredCallFlags.HasFlag(CallFlags.AllowModifyStates))
                {
                    safeMethods.Add(metadata.Name);
                }
                methods.Add(metadata.Name, metadata);
            }
            this.Manifest = new ContractManifest
            {
                Groups             = System.Array.Empty <ContractGroup>(),
                Features           = ContractFeatures.NoProperty,
                SupportedStandards = new string[0],
                Abi = new ContractAbi()
                {
                    Hash    = Hash,
                    Events  = System.Array.Empty <ContractEventDescriptor>(),
                    Methods = descriptors.ToArray()
                },
                Permissions = new[] { ContractPermission.DefaultPermission },
                Trusts      = WildcardContainer <UInt160> .Create(),
                SafeMethods = WildcardContainer <string> .Create(safeMethods.ToArray()),
                Extra       = null
            };
            contractsList.Add(this);
            contractsNameDictionary.Add(Name, this);
            contractsHashDictionary.Add(Hash, this);
        }
Beispiel #2
0
 internal async void Invoke(ApplicationEngine engine, byte version)
 {
     try
     {
         if (version != 0)
         {
             throw new InvalidOperationException($"The native contract of version {version} is not active.");
         }
         ExecutionContext       context = engine.CurrentContext;
         ContractMethodMetadata method  = methods[context.InstructionPointer];
         ExecutionContextState  state   = context.GetState <ExecutionContextState>();
         if (!state.CallFlags.HasFlag(method.RequiredCallFlags))
         {
             throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}.");
         }
         engine.AddGas(method.CpuFee * Policy.GetExecFeeFactor(engine.Snapshot) + method.StorageFee * Policy.GetStoragePrice(engine.Snapshot));
         List <object> parameters = new List <object>();
         if (method.NeedApplicationEngine)
         {
             parameters.Add(engine);
         }
         if (method.NeedSnapshot)
         {
             parameters.Add(engine.Snapshot);
         }
         for (int i = 0; i < method.Parameters.Length; i++)
         {
             parameters.Add(engine.Convert(context.EvaluationStack.Pop(), method.Parameters[i]));
         }
         object returnValue = method.Handler.Invoke(this, parameters.ToArray());
         if (returnValue is ContractTask task)
         {
             await task;
             returnValue = task.GetResult();
         }
         if (method.Handler.ReturnType != typeof(void) && method.Handler.ReturnType != typeof(ContractTask))
         {
             context.EvaluationStack.Push(engine.Convert(returnValue));
         }
     }
     catch (Exception ex)
     {
         engine.Throw(ex);
     }
 }
Beispiel #3
0
        internal void Invoke(ApplicationEngine engine, byte version)
        {
            if (ActiveBlockIndex > Ledger.CurrentIndex(engine.Snapshot))
            {
                throw new InvalidOperationException($"The native contract {Name} is not active.");
            }
            if (version != 0)
            {
                throw new InvalidOperationException($"The native contract of version {version} is not active.");
            }
            ExecutionContext       context = engine.CurrentContext;
            ContractMethodMetadata method  = methods[context.InstructionPointer];
            ExecutionContextState  state   = context.GetState <ExecutionContextState>();

            if (!state.CallFlags.HasFlag(method.RequiredCallFlags))
            {
                throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}.");
            }
            engine.AddGas(method.Price);
            List <object> parameters = new List <object>();

            if (method.NeedApplicationEngine)
            {
                parameters.Add(engine);
            }
            if (method.NeedSnapshot)
            {
                parameters.Add(engine.Snapshot);
            }
            for (int i = 0; i < method.Parameters.Length; i++)
            {
                parameters.Add(engine.Convert(context.EvaluationStack.Pop(), method.Parameters[i]));
            }
            object returnValue = method.Handler.Invoke(this, parameters.ToArray());

            if (method.Handler.ReturnType != typeof(void))
            {
                context.EvaluationStack.Push(engine.Convert(returnValue));
            }
        }
Beispiel #4
0
        internal void Invoke(ApplicationEngine engine)
        {
            if (!engine.CurrentScriptHash.Equals(Hash))
            {
                throw new InvalidOperationException("It is not allowed to use Neo.Native.Call directly to call native contracts. System.Contract.Call should be used.");
            }
            ExecutionContext       context   = engine.CurrentContext;
            string                 operation = context.EvaluationStack.Pop().GetString();
            Array                  args      = context.EvaluationStack.Pop <Array>();
            ContractMethodMetadata method    = methods[operation];
            ExecutionContextState  state     = context.GetState <ExecutionContextState>();

            if (!state.CallFlags.HasFlag(method.RequiredCallFlags))
            {
                throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}.");
            }
            engine.AddGas(method.Price);
            List <object> parameters = new List <object>();

            if (method.NeedApplicationEngine)
            {
                parameters.Add(engine);
            }
            if (method.NeedSnapshot)
            {
                parameters.Add(engine.Snapshot);
            }
            for (int i = 0; i < method.Parameters.Length; i++)
            {
                StackItem item = i < args.Count ? args[i] : StackItem.Null;
                parameters.Add(engine.Convert(item, method.Parameters[i]));
            }
            object returnValue = method.Handler.Invoke(this, parameters.ToArray());

            if (method.Handler.ReturnType != typeof(void))
            {
                context.EvaluationStack.Push(engine.Convert(returnValue));
            }
        }
Beispiel #5
0
        protected NativeContract()
        {
            this.Id = --id_counter;
            byte[] script;
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitPush(Id);
                sb.EmitSysCall(ApplicationEngine.System_Contract_CallNative);
                script = sb.ToArray();
            }
            this.Nef = new NefFile
            {
                Compiler = nameof(ScriptBuilder),
                Version  = "3.0",
                Tokens   = System.Array.Empty <MethodToken>(),
                Script   = script
            };
            this.Nef.CheckSum = NefFile.ComputeChecksum(Nef);
            this.Hash         = Helper.GetContractHash(UInt160.Zero, script);
            List <ContractMethodDescriptor> descriptors = new List <ContractMethodDescriptor>();

            foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                ContractMethodAttribute attribute = member.GetCustomAttribute <ContractMethodAttribute>();
                if (attribute is null)
                {
                    continue;
                }
                ContractMethodMetadata metadata = new ContractMethodMetadata(member, attribute);
                descriptors.Add(new ContractMethodDescriptor
                {
                    Name       = metadata.Name,
                    ReturnType = ToParameterType(metadata.Handler.ReturnType),
                    Parameters = metadata.Parameters.Select(p => new ContractParameterDefinition {
                        Type = ToParameterType(p.Type), Name = p.Name
                    }).ToArray(),
                    Safe = (attribute.RequiredCallFlags & ~CallFlags.ReadOnly) == 0
                });
                methods.Add(metadata.Name, metadata);
            }
            this.Manifest = new ContractManifest
            {
                Name               = Name,
                Groups             = System.Array.Empty <ContractGroup>(),
                SupportedStandards = new string[0],
                Abi = new ContractAbi()
                {
                    Events  = System.Array.Empty <ContractEventDescriptor>(),
                    Methods = descriptors.ToArray()
                },
                Permissions = new[] { ContractPermission.DefaultPermission },
                Trusts      = WildcardContainer <UInt160> .Create(),
                Extra       = null
            };
            if (ProtocolSettings.Default.NativeActivations.TryGetValue(Name, out uint activationIndex))
            {
                this.ActiveBlockIndex = activationIndex;
            }
            contractsList.Add(this);
            contractsIdDictionary.Add(Id, this);
            contractsHashDictionary.Add(Hash, this);
        }