예제 #1
0
        /// <summary>
        /// Deploy Contract, return signed transaction
        /// </summary>
        /// <param name="contractScript">contract script</param>
        /// <param name="manifest">contract manifest</param>
        /// <param name="key">sender KeyPair</param>
        /// <returns></returns>
        public Transaction CreateDeployContractTx(byte[] contractScript, ContractManifest manifest, KeyPair key)
        {
            byte[] script;
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitSysCall(ApplicationEngine.System_Contract_Create, contractScript, manifest.ToString());
                script = sb.ToArray();
            }
            UInt160 sender = Contract.CreateSignatureRedeemScript(key.PublicKey).ToScriptHash();

            Signer[] signers = new[] { new Signer {
                                           Scopes = WitnessScope.CalledByEntry, Account = sender
                                       } };

            Transaction tx = new TransactionManager(rpcClient)
                             .MakeTransaction(script, signers)
                             .AddSignature(key)
                             .Sign()
                             .Tx;

            return(tx);
        }
예제 #2
0
        public void Test_InvocationCounter()
        {
            _engine.AddEntryScript("./TestClasses/Contract_Runtime.cs");

            // We need a new TestEngine because invocationCounter it's shared between them

            var contract = _engine.EntryScriptHash;
            var engine   = new TestEngine(TriggerType.Application, new DummyVerificable(), new TestDataCache());

            engine.Snapshot.ContractAdd(new ContractState()
            {
                Hash     = contract,
                Nef      = _engine.Nef,
                Manifest = ContractManifest.FromJson(_engine.Manifest),
            });

            using (ScriptBuilder sb = new())
            {
                // First
                sb.EmitDynamicCall(contract, "getInvocationCounter");
                // Second
                sb.EmitDynamicCall(contract, "getInvocationCounter");
                engine.LoadScript(sb.ToArray());
            }

            // Check

            Assert.AreEqual(VMState.HALT, engine.Execute());
            Assert.AreEqual(2, engine.ResultStack.Count);

            var item = engine.ResultStack.Pop();

            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(0x02, item.GetInteger());

            item = engine.ResultStack.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(0x01, item.GetInteger());
        }
예제 #3
0
        public void TestGetContractState()
        {
            var sb = new ScriptBuilder();

            sb.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter);

            ContractState state = new ContractState
            {
                Script   = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(sb.ToArray()).ToArray(),
                Manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"))
            };

            JObject response = CreateResponse(1);

            response["result"] = state.ToJson();
            MockResponse(response.ToString());

            var result = rpc.GetContractState("17694b31cc7ee215cea2ded146e0b2b28768fc46");

            Assert.AreEqual(state.Script.ToHexString(), result.Script.ToHexString());
            Assert.AreEqual(state.Manifest.Abi.EntryPoint.Name, result.Manifest.Abi.EntryPoint.Name);
        }
        private async ContractTask<ContractState> Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data)
        {
            if (engine.ScriptContainer is not Transaction tx)
                throw new InvalidOperationException();
            if (nefFile.Length == 0)
                throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}");
            if (manifest.Length == 0)
                throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");

            engine.AddValt(Math.Max(
                engine.StoragePrice * (nefFile.Length + manifest.Length),
                GetMinimumDeploymentFee(engine.Snapshot)
                ));

            NefFile nef = nefFile.AsSerializable<NefFile>();
            ContractManifest parsedManifest = ContractManifest.Parse(manifest);
            Helper.Check(nef.Script, parsedManifest.Abi);
            UInt160 hash = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name);
            StorageKey key = CreateStorageKey(Prefix_Contract).Add(hash);
            if (engine.Snapshot.Contains(key))
                throw new InvalidOperationException($"Contract Already Exists: {hash}");
            ContractState contract = new()
            {
                Id = GetNextAvailableId(engine.Snapshot),
                UpdateCounter = 0,
                Nef = nef,
                Hash = hash,
                Manifest = parsedManifest
            };

            if (!contract.Manifest.IsValid(hash)) throw new InvalidOperationException($"Invalid Manifest Hash: {hash}");

            engine.Snapshot.Add(key, new StorageItem(contract));

            await OnDeploy(engine, contract, data, false);

            return contract;
        }
예제 #5
0
        public void Test_InvocationCounter()
        {
            // We need a new TestEngine because invocationCounter it's shared between them

            var contract = _engine.EntryScriptHash;
            var engine   = new TestEngine(TriggerType.Application, new DummyVerificable());

            engine.Snapshot.Contracts.Add(contract, new Ledger.ContractState()
            {
                Script   = _engine.InvocationStack.Peek().Script,
                Manifest = ContractManifest.FromJson(JObject.Parse(_engine.Build("./TestClasses/Contract_Runtime.cs").finalManifest)),
            });

            using (ScriptBuilder sb = new ScriptBuilder())
            {
                // First
                sb.EmitAppCall(contract, "getInvocationCounter");
                // Second
                sb.EmitAppCall(contract, "getInvocationCounter");

                engine.LoadScript(sb.ToArray());
            }

            // Check

            Assert.AreEqual(VMState.HALT, engine.Execute());
            Assert.AreEqual(2, engine.ResultStack.Count);

            var item = engine.ResultStack.Pop();

            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(0x02, item.GetInteger());

            item = engine.ResultStack.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(0x01, item.GetInteger());
        }
예제 #6
0
        public void TestContract_Create()
        {
            var engine = GetEngine(false, true);
            var script = new byte[1024 * 1024 + 1];

            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();

            string manifestStr = new string(new char[ContractManifest.MaxLength + 1]);

            script = new byte[] { 0x01 };
            engine.CurrentContext.EvaluationStack.Push(manifestStr);
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();

            var manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"));

            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();

            manifest.Abi.Hash = script.ToScriptHash();
            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeTrue();

            var mockSnapshot = new Mock <Snapshot>();
            var state        = TestUtils.GetContract();

            mockSnapshot.SetupGet(p => p.Contracts).Returns(new TestDataCache <UInt160, ContractState>(state.ScriptHash, state));
            engine = new ApplicationEngine(TriggerType.Application, null, mockSnapshot.Object, 0);
            engine.LoadScript(new byte[] { 0x01 });
            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(state.Script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();
        }
예제 #7
0
        public void TestContract_Create()
        {
            var engine = GetEngine(false, true);
            var script = new byte[1024 * 1024 + 1];

            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();

            string manifestStr = new string(new char[ContractManifest.MaxLength + 1]);

            script = new byte[] { 0x01 };
            engine.CurrentContext.EvaluationStack.Push(manifestStr);
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();

            var manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"));

            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();

            manifest.Abi.Hash = script.ToScriptHash();
            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeTrue();

            var snapshot = Blockchain.Singleton.GetSnapshot();
            var state    = TestUtils.GetContract();

            snapshot.Contracts.Add(state.ScriptHash, state);
            engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0);
            engine.LoadScript(new byte[] { 0x01 });
            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(state.Script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse();
        }
예제 #8
0
        public async Task TestDeployContract()
        {
            byte[] script;
            var    manifest = new ContractManifest()
            {
                Permissions = new[] { ContractPermission.DefaultPermission },
                Abi         = new ContractAbi()
                {
                    Hash    = new byte[1].ToScriptHash(),
                    Events  = new ContractEventDescriptor[0],
                    Methods = new ContractMethodDescriptor[0]
                },
                Groups             = new ContractGroup[0],
                SafeMethods        = WildcardContainer <string> .Create(),
                Trusts             = WildcardContainer <UInt160> .Create(),
                SupportedStandards = new string[]
                {
                    "NEP-10"
                },
                Extra = null,
            };

            manifest.Features = ContractFeatures.HasStorage | ContractFeatures.Payable;
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitSysCall(ApplicationEngine.System_Contract_Create, new byte[1], manifest.ToString());
                script = sb.ToArray();
            }

            UT_TransactionManager.MockInvokeScript(rpcClientMock, script, new ContractParameter());

            ContractClient contractClient = new ContractClient(rpcClientMock.Object);
            var            result         = await contractClient.CreateDeployContractTxAsync(new byte[1], manifest, keyPair1);

            Assert.IsNotNull(result);
        }
예제 #9
0
        public void TestGetHash()
        {
            var temp = ContractManifest.CreateDefault(UInt160.Zero);

            Assert.AreEqual(temp.Abi.Hash, temp.Hash);
        }
예제 #10
0
        public void TestIsAllowed()
        {
            ContractManifest   contractManifest1   = TestUtils.CreateDefaultManifest();
            ContractPermission contractPermission1 = ContractPermission.DefaultPermission;

            contractPermission1.Contract = ContractPermissionDescriptor.Create(UInt160.Zero);
            Assert.AreEqual(true, contractPermission1.IsAllowed(new ContractState()
            {
                Hash = UInt160.Zero, Manifest = contractManifest1
            }, "AAA"));
            contractPermission1.Contract = ContractPermissionDescriptor.CreateWildcard();

            ContractManifest   contractManifest2   = TestUtils.CreateDefaultManifest();
            ContractPermission contractPermission2 = ContractPermission.DefaultPermission;

            contractPermission2.Contract = ContractPermissionDescriptor.Create(UInt160.Parse("0x0000000000000000000000000000000000000001"));
            Assert.AreEqual(false, contractPermission2.IsAllowed(new ContractState()
            {
                Hash = UInt160.Zero, Manifest = contractManifest2
            }, "AAA"));
            contractPermission2.Contract = ContractPermissionDescriptor.CreateWildcard();

            Random random3 = new Random();

            byte[] privateKey3 = new byte[32];
            random3.NextBytes(privateKey3);
            ECPoint          publicKey3        = ECCurve.Secp256r1.G * privateKey3;
            ContractManifest contractManifest3 = TestUtils.CreateDefaultManifest();

            contractManifest3.Groups = new ContractGroup[] { new ContractGroup()
                                                             {
                                                                 PubKey = publicKey3
                                                             } };
            ContractPermission contractPermission3 = ContractPermission.DefaultPermission;

            contractPermission3.Contract = ContractPermissionDescriptor.Create(publicKey3);
            Assert.AreEqual(true, contractPermission3.IsAllowed(new ContractState()
            {
                Hash = UInt160.Zero, Manifest = contractManifest3
            }, "AAA"));
            contractPermission3.Contract = ContractPermissionDescriptor.CreateWildcard();

            Random random4 = new Random();

            byte[] privateKey41 = new byte[32];
            random4.NextBytes(privateKey41);
            ECPoint publicKey41 = ECCurve.Secp256r1.G * privateKey41;

            byte[] privateKey42 = new byte[32];
            random4.NextBytes(privateKey42);
            ECPoint          publicKey42       = ECCurve.Secp256r1.G * privateKey42;
            ContractManifest contractManifest4 = TestUtils.CreateDefaultManifest();

            contractManifest4.Groups = new ContractGroup[] { new ContractGroup()
                                                             {
                                                                 PubKey = publicKey42
                                                             } };
            ContractPermission contractPermission4 = ContractPermission.DefaultPermission;

            contractPermission4.Contract = ContractPermissionDescriptor.Create(publicKey41);
            Assert.AreEqual(false, contractPermission4.IsAllowed(new ContractState()
            {
                Hash = UInt160.Zero, Manifest = contractManifest4
            }, "AAA"));
            contractPermission4.Contract = ContractPermissionDescriptor.CreateWildcard();
        }
예제 #11
0
        private ContractState Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data)
        {
            if (engine.ScriptContainer is not Transaction tx)
            {
                throw new InvalidOperationException();
            }
            if (nefFile.Length == 0)
            {
                throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}");
            }
            if (manifest.Length == 0)
            {
                throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");
            }

            engine.AddGas(Math.Max(
                              engine.StoragePrice * (nefFile.Length + manifest.Length),
                              GetMinimumDeploymentFee(engine.Snapshot)
                              ));

            NefFile          nef            = nefFile.AsSerializable <NefFile>();
            ContractManifest parsedManifest = ContractManifest.Parse(manifest);

            Check(nef.Script, parsedManifest.Abi);
            UInt160    hash = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name);
            StorageKey key  = CreateStorageKey(Prefix_Contract).Add(hash);

            if (engine.Snapshot.Contains(key))
            {
                throw new InvalidOperationException($"Contract Already Exists: {hash}");
            }
            ContractState contract = new ContractState
            {
                Id            = GetNextAvailableId(engine.Snapshot),
                UpdateCounter = 0,
                Nef           = nef,
                Hash          = hash,
                Manifest      = parsedManifest
            };

            if (!contract.Manifest.IsValid(hash))
            {
                throw new InvalidOperationException($"Invalid Manifest Hash: {hash}");
            }

            engine.Snapshot.Add(key, new StorageItem(contract));

            // Execute _deploy

            ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2);

            if (md != null)
            {
                engine.CallFromNativeContract(Hash, hash, md.Name, data, false);
            }

            engine.SendNotification(Hash, "Deploy", new VM.Types.Array {
                contract.Hash.ToArray()
            });

            return(contract);
        }
예제 #12
0
        public void Test_CreateCallDestroy()
        {
            // Create

            var entryScript = _engine.ScriptEntry;
            var script      = _engine.Build("./TestClasses/Contract_Create.cs");
            var manifest    = ContractManifest.FromJson(JObject.Parse(script.finalManifest));
            var nef         = new NefFile()
            {
                Script = script.finalNEFScript, Compiler = "unit-test-1.0", Tokens = System.Array.Empty <MethodToken>()
            };

            nef.CheckSum = NefFile.ComputeChecksum(nef);

            var hash = Helper.GetContractHash((_engine.ScriptContainer as Transaction).Sender, nef.CheckSum, manifest.Name);

            // Create

            _engine.Reset();
            var result = _engine.ExecuteTestCaseStandard("create", nef.ToArray(), manifest.ToJson().ToString());

            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            var item = result.Pop();

            Assert.IsInstanceOfType(item, typeof(Array));
            var itemArray = item as Array;

            Assert.AreEqual(1, itemArray[0].GetInteger());                                                                   // Id
            Assert.AreEqual(0, itemArray[1].GetInteger());                                                                   // UpdateCounter
            Assert.AreEqual(hash.ToArray(), itemArray[2]);                                                                   // Hash
            Assert.AreEqual(nef.ToJson().AsString(), itemArray[3].GetSpan().AsSerializable <NefFile>().ToJson().AsString()); // Nef
            var ritem = new ContractManifest();

            ((IInteroperable)ritem).FromStackItem(itemArray[4]);
            Assert.AreEqual(manifest.ToString(), ritem.ToString()); // Manifest

            // Call

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", hash.ToArray(), "oldContract", (byte)CallFlags.All, new Array());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(123, item.GetInteger());

            // Destroy

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("destroy", entryScript.nefFile);
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(0, result.Count);

            // Check again for failures

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", hash.ToArray());
            Assert.AreEqual(VMState.FAULT, _engine.State);
            Assert.AreEqual(0, result.Count);
        }
예제 #13
0
        public void Test_CreateCallDestroy()
        {
            // Create

            TestEngine engine = new();

            engine.AddEntryScript("./TestClasses/Contract_Create.cs");
            var manifest = ContractManifest.FromJson(engine.Manifest);
            var nef      = new NefFile()
            {
                Script = engine.Nef.Script, Compiler = engine.Nef.Compiler, Source = engine.Nef.Source, Tokens = engine.Nef.Tokens
            };

            nef.CheckSum = NefFile.ComputeChecksum(nef);

            var hash = Helper.GetContractHash((_engine.ScriptContainer as Transaction).Sender, nef.CheckSum, manifest.Name);

            // Create

            _engine.Reset();
            var result = _engine.ExecuteTestCaseStandard("create", nef.ToArray(), manifest.ToJson().ToString());

            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            var item = result.Pop();

            Assert.IsInstanceOfType(item, typeof(Array));
            var itemArray = item as Array;

            Assert.AreEqual(1, itemArray[0].GetInteger());                                                                             // Id
            Assert.AreEqual(0, itemArray[1].GetInteger());                                                                             // UpdateCounter
            Assert.AreEqual(hash.ToArray(), itemArray[2]);                                                                             // Hash
            Assert.AreEqual(nef.ToJson().AsString(), itemArray[3].GetSpan().ToArray().AsSerializable <NefFile>().ToJson().AsString()); // Nef
            var ritem = new ContractManifest();

            ((IInteroperable)ritem).FromStackItem(itemArray[4]);
            Assert.AreEqual(manifest.ToString(), ritem.ToString()); // Manifest

            // Call

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", hash.ToArray(), "oldContract", (byte)CallFlags.All, new Array());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(ByteString));
            Assert.AreEqual(manifest.Name, item.GetString());

            // Destroy

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("destroy", _engine.Nef);
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(0, result.Count);

            // Check again for failures

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", hash.ToArray());
            Assert.AreEqual(VMState.FAULT, _engine.State);
            Assert.AreEqual(0, result.Count);
        }
예제 #14
0
        public async Task <object> DeployContract(string nefPath, string manifestPath = null, bool sendTx = false, UInt160 sender = null)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (nefPath.IsNull())
            {
                return(Error(ErrorCode.ParameterIsNull, "nefPath is empty."));
            }
            if (manifestPath.IsNull())
            {
                manifestPath = Path.ChangeExtension(nefPath, ".manifest.json");
            }
            // Read nef
            NefFile nefFile = ReadNefFile(nefPath);
            // Read manifest
            ContractManifest manifest = ReadManifestFile(manifestPath);

            // Basic script checks
            await CheckBadOpcode(nefFile.Script);

            // Build script
            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", nefFile.ToArray(),
                               manifest.ToJson().ToString());
            //sb.EmitAppCall(NativeContract.Management.Hash, "deploy", nefFile.ToArray(), manifest.ToJson().ToString());
            var script = sb.ToArray();

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(Helpers.GetDefaultSnapshot(), script, sender);
            }
            catch (InvalidOperationException ex)
            {
                return(Error(ErrorCode.EngineFault, ex.GetExMessage()));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            UInt160 hash = SmartContract.Helper.GetContractHash(tx.Sender, nefFile.CheckSum, manifest.Name);

            var oldContract = hash.GetContract();

            if (oldContract != null)
            {
                return(Error(ErrorCode.ContractAlreadyExist));
            }
            var result = new DeployResultModel
            {
                ContractHash = hash,
                GasConsumed  = new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)
            };

            if (sendTx)
            {
                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                result.TxId = tx.Hash;
            }
            return(result);
        }
예제 #15
0
        public void Runtime_GetNotifications_Test()
        {
            UInt160 scriptHash2;
            var     snapshot = Blockchain.Singleton.GetSnapshot();

            using (var script = new ScriptBuilder())
            {
                // Drop arguments

                script.Emit(OpCode.NIP);

                // Notify method

                script.EmitSysCall(InteropService.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.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.Runtime.Notify);

                    // Call script

                    script.EmitAppCall(scriptHash2, "test");

                    // Drop return

                    script.Emit(OpCode.DROP);

                    // Receive all notifications

                    script.Emit(OpCode.PUSHNULL);
                    script.EmitSysCall(InteropService.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.Runtime.Notify);

                    // Call script

                    script.EmitAppCall(scriptHash2, "test");

                    // Drop return

                    script.Emit(OpCode.DROP);

                    // Receive all notifications

                    script.EmitPush(scriptHash2.ToArray());
                    script.EmitSysCall(InteropService.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);
        }
예제 #16
0
 void ICloneable <ContractState> .FromReplica(ContractState replica)
 {
     Id       = replica.Id;
     Script   = replica.Script;
     Manifest = replica.Manifest.Clone();
 }
예제 #17
0
        public void Test_Update()
        {
            // Create

            var script   = _engine.Build("./TestClasses/Contract_CreateAndUpdate.cs");
            var manifest = ContractManifest.FromJson(JObject.Parse(script.finalManifest));

            var scriptUpdate   = _engine.Build("./TestClasses/Contract_Update.cs");
            var manifestUpdate = ContractManifest.FromJson(JObject.Parse(scriptUpdate.finalManifest));

            // Check first

            _engine.Reset();
            var result = _engine.ExecuteTestCaseStandard("call", manifest.Hash.ToArray(), "oldContract", new Array());

            Assert.AreEqual(VMState.FAULT, _engine.State);
            Assert.AreEqual(0, result.Count);

            _engine.Reset();
            _ = _engine.ExecuteTestCaseStandard("call", manifestUpdate.Hash.ToArray(), "newContract", new Array());
            Assert.AreEqual(VMState.FAULT, _engine.State);

            // Create

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("create", script.finalNEF, manifest.ToJson().ToString());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            var item = result.Pop();

            Assert.IsInstanceOfType(item, typeof(Array));
            var itemArray = item as Array;

            Assert.AreEqual(script.finalNEF, itemArray[0]);                 // Script
            Assert.AreEqual(manifest.ToString(), itemArray[1].GetString()); // Manifest
            Assert.AreEqual(false, itemArray[2]);                           // HasStorage
            Assert.AreEqual(false, itemArray[3]);                           // Payable

            // Call & Update

            _engine.Reset();
            var args = new Array
            {
                scriptUpdate.finalNEF,
                manifestUpdate.ToJson().ToString()
            };

            result = _engine.ExecuteTestCaseStandard("call", manifest.Hash.ToArray(), "oldContract", args);
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(123, item.GetInteger());

            // Call Again

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", manifestUpdate.Hash.ToArray(), "newContract", new Array());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(124, item.GetInteger());

            // Check again for failures

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", manifest.Hash.ToArray(), "oldContract", new Array());
            Assert.AreEqual(VMState.FAULT, _engine.State);
            Assert.AreEqual(0, result.Count);
        }
예제 #18
0
 void ISerializable.Deserialize(BinaryReader reader)
 {
     Id       = reader.ReadInt32();
     Script   = reader.ReadVarBytes();
     Manifest = reader.ReadSerializable <ContractManifest>();
 }
예제 #19
0
        private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, out NefFile nef, out ContractManifest manifest)
        {
            if (string.IsNullOrEmpty(manifestFilePath))
            {
                manifestFilePath = Path.ChangeExtension(nefFilePath, ".manifest.json");
            }

            // Read manifest

            var info = new FileInfo(manifestFilePath);

            if (!info.Exists || info.Length >= Transaction.MaxTransactionSize)
            {
                throw new ArgumentException(nameof(manifestFilePath));
            }

            manifest = ContractManifest.Parse(File.ReadAllBytes(manifestFilePath));

            // Read nef

            info = new FileInfo(nefFilePath);
            if (!info.Exists || info.Length >= Transaction.MaxTransactionSize)
            {
                throw new ArgumentException(nameof(nefFilePath));
            }

            using (var stream = new BinaryReader(File.OpenRead(nefFilePath), Utility.StrictUTF8, false))
            {
                nef = stream.ReadSerializable <NefFile>();
            }

            // Basic script checks

            Script script = new Script(nef.Script);

            for (var i = 0; i < script.Length;)
            {
                // Check bad opcodes

                Instruction inst = script.GetInstruction(i);
                if (inst is null || !Enum.IsDefined(typeof(OpCode), inst.OpCode))
                {
                    throw new FormatException($"OpCode not found at {i}-{((byte)inst.OpCode).ToString("x2")}");
                }
                i += inst.Size;
            }

            // Build script

            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", nef.ToArray(), manifest.ToJson().ToString());
                return(sb.ToArray());
            }
        }
        public void Test_Update()
        {
            // Create

            var script   = _engine.Build("./TestClasses/Contract_CreateAndUpdate.cs");
            var manifest = ContractManifest.FromJson(JObject.Parse(script.finalManifest));
            var nef      = new NefFile()
            {
                Script = script.finalNEFScript, Compiler = "unit-test", Version = "1.0"
            };
            var hash = Helper.GetContractHash((_engine.ScriptContainer as Transaction).Sender, nef.Script);

            nef.CheckSum = NefFile.ComputeChecksum(nef);

            var scriptUpdate   = _engine.Build("./TestClasses/Contract_Update.cs");
            var manifestUpdate = ContractManifest.FromJson(JObject.Parse(scriptUpdate.finalManifest));

            // Create

            _engine.Reset();
            var result = _engine.ExecuteTestCaseStandard("create", nef.ToArray(), manifest.ToJson().ToString());

            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            var item = result.Pop();

            Assert.IsInstanceOfType(item, typeof(Array));
            var itemArray = item as Array;

            Assert.AreEqual(1, itemArray[0].GetInteger());                  // Id
            Assert.AreEqual(0, itemArray[1].GetInteger());                  // UpdateCounter
            Assert.AreEqual(hash.ToArray(), itemArray[2]);                  // Hash
            Assert.AreEqual(script.finalNEFScript, itemArray[3]);           // Script
            Assert.AreEqual(manifest.ToString(), itemArray[4].GetString()); // Manifest

            // Call & Update

            _engine.Reset();
            nef.Script   = scriptUpdate.finalNEFScript;
            nef.CheckSum = NefFile.ComputeChecksum(nef);
            var args = new Array
            {
                nef.ToArray(),
                manifestUpdate.ToJson().ToString()
            };

            result = _engine.ExecuteTestCaseStandard("call", hash.ToArray(), "oldContract", args);
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(123, item.GetInteger());

            // Call Again

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", hash.ToArray(), "newContract", new Array());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(124, item.GetInteger());

            // Check again for failures

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", hash.ToArray(), "oldContract", new Array());
            Assert.AreEqual(VMState.FAULT, _engine.State);
            Assert.AreEqual(0, result.Count);
        }
예제 #21
0
        public void TestGetSize()
        {
            var temp = ContractManifest.CreateDefault(UInt160.Zero);

            Assert.AreEqual(366, temp.Size);
        }
        public void Test_Update()
        {
            // Create

            byte[] scriptUpdate;
            using (var scriptBuilder = new ScriptBuilder())
            {
                // Drop arguments

                scriptBuilder.Emit(VM.OpCode.DROP);
                scriptBuilder.Emit(VM.OpCode.DROP);

                // Return 124

                scriptBuilder.EmitPush(123);
                scriptBuilder.Emit(VM.OpCode.INC);
                scriptUpdate = scriptBuilder.ToArray();
            }

            var manifestUpdate = ContractManifest.CreateDefault(scriptUpdate.ToScriptHash());

            byte[] script;
            using (var scriptBuilder = new ScriptBuilder())
            {
                // Drop arguments

                scriptBuilder.Emit(VM.OpCode.DROP);
                scriptBuilder.Emit(VM.OpCode.DROP);

                // Return 123

                scriptBuilder.EmitPush(123);

                // Update

                scriptBuilder.EmitSysCall(InteropService.Neo_Contract_Update, scriptUpdate, manifestUpdate.ToJson().ToString());
                script = scriptBuilder.ToArray();
            }

            var manifest = ContractManifest.CreateDefault(script.ToScriptHash());

            // Check first

            _engine.Reset();
            var result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray());

            Assert.AreEqual(VMState.FAULT, _engine.State);

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("Call", manifestUpdate.Hash.ToArray());
            Assert.AreEqual(VMState.FAULT, _engine.State);

            // Create

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("Create", script, manifest.ToJson().ToString());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            var item = result.Pop();

            Assert.IsInstanceOfType(item, typeof(InteropInterface <Ledger.ContractState>));
            Assert.AreEqual(manifest.Hash,
                            ((InteropInterface <Ledger.ContractState>)item).GetInterface <Ledger.ContractState>().ScriptHash);

            // Call & Update

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray(), Null.Null, Null.Null);
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(ByteArray));
            Assert.AreEqual(123, item.GetBigInteger());

            // Call Again

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("Call", manifestUpdate.Hash.ToArray(), Null.Null, Null.Null);
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(124, item.GetBigInteger());

            // Check again for failures

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray());
            Assert.AreEqual(VMState.FAULT, _engine.State);
        }
예제 #23
0
        public void TestGenerator()
        {
            ContractManifest contractManifest = new ContractManifest();

            Assert.IsNotNull(contractManifest);
        }
예제 #24
0
        public async Task <object> UpdateContract(UInt160 contractHash, string nefPath, string manifestPath = null, bool sendTx = false, UInt160[] cosigners = null)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (nefPath.IsNull())
            {
                return(Error(ErrorCode.ParameterIsNull, "nefPath is empty."));
            }
            if (manifestPath.IsNull())
            {
                manifestPath = Path.ChangeExtension(nefPath, ".manifest.json");
            }
            // Read nef
            NefFile nefFile = ReadNefFile(nefPath);
            // Read manifest
            ContractManifest manifest = ReadManifestFile(manifestPath);

            // Basic script checks
            await CheckBadOpcode(nefFile.Script);

            // Build script
            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitDynamicCall(contractHash, "update", nefFile.ToArray(), manifest.ToJson().ToString(), null);
            var script = sb.ToArray();

            var singers = new List <Signer> {
            };

            if (cosigners != null)
            {
                singers.AddRange(cosigners.Select(s => new Signer()
                {
                    Account = s, Scopes = WitnessScope.Global
                }));
            }
            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(Helpers.GetDefaultSnapshot(), script, null, singers.ToArray());
            }
            catch (InvalidOperationException ex)
            {
                return(Error(ErrorCode.EngineFault, ex.GetExMessage()));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            var result = new DeployResultModel
            {
                ContractHash = contractHash,
                GasConsumed  = new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)
            };

            if (sendTx)
            {
                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                result.TxId = tx.Hash;
            }
            return(result);
        }
예제 #25
0
        public void GetContract()
        {
            var contract = new ContractState()
            {
                Hash = new byte[] { 0x01, 0x02, 0x03 }.ToScriptHash(),
                Nef = new NefFile()
                {
                    Script   = new byte[] { 0x01, 0x02, 0x03 },
                    Compiler = "neon-test",
                    Tokens   = System.Array.Empty <MethodToken>()
                },
                Manifest = new ContractManifest()
                {
                    Name = "Name",
                    SupportedStandards = System.Array.Empty <string>(),
                    Groups             = System.Array.Empty <ContractGroup>(),
                    Trusts             = WildcardContainer <ContractPermissionDescriptor> .Create(),
                    Permissions        = System.Array.Empty <ContractPermission>(),
                    Abi = new ContractAbi()
                    {
                        Methods = System.Array.Empty <ContractMethodDescriptor>(),
                        Events  = System.Array.Empty <ContractEventDescriptor>(),
                    },
                }
            };

            _engine.Snapshot.ContractAdd(contract);

            // Not found

            _engine.Reset();
            var result = _engine.ExecuteTestCaseStandard("getContract", new ByteString(UInt160.Zero.ToArray()), new ByteString(new byte[20]));

            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            var item = result.Pop();

            Assert.IsInstanceOfType(item, typeof(Null));

            // Found + Manifest

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("getContract", new ByteString(contract.Hash.ToArray()), new ByteString(Utility.StrictUTF8.GetBytes("Manifest")));
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Struct));
            var ritem = new ContractManifest();

            ((IInteroperable)ritem).FromStackItem(item);
            Assert.AreEqual(contract.Manifest.ToString(), ritem.ToString());

            // Found + UpdateCounter

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("getContract", new ByteString(contract.Hash.ToArray()), new ByteString(Utility.StrictUTF8.GetBytes("UpdateCounter")));
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(0, item.GetInteger());

            // Found + Id

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("getContract", new ByteString(contract.Hash.ToArray()), new ByteString(Utility.StrictUTF8.GetBytes("Id")));
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(0, item.GetInteger());

            // Found + Hash

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("getContract", new ByteString(contract.Hash.ToArray()), new ByteString(Utility.StrictUTF8.GetBytes("Hash")));
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(ByteString));
            CollectionAssert.AreEqual(contract.Hash.ToArray(), item.GetSpan().ToArray());

            // Found + Uknown property

            _engine.Reset();
            _ = _engine.ExecuteTestCaseStandard("getContract", new ByteString(contract.Hash.ToArray()), new ByteString(Utility.StrictUTF8.GetBytes("ASD")));
            Assert.AreEqual(VMState.FAULT, _engine.State);
        }
예제 #26
0
        public void Test_Update()
        {
            // Create

            var script   = _engine.Build("./TestClasses/Contract_CreateAndUpdate.cs");
            var manifest = ContractManifest.FromJson(JObject.Parse(script.finalManifest));

            var scriptUpdate   = _engine.Build("./TestClasses/Contract_Update.cs");
            var manifestUpdate = ContractManifest.FromJson(JObject.Parse(scriptUpdate.finalManifest));

            // Check first

            _engine.Reset();
            var result = _engine.ExecuteTestCaseStandard("call", manifest.Hash.ToArray(), "oldContract", new Array());

            Assert.AreEqual(VMState.FAULT, _engine.State);
            Assert.AreEqual(0, result.Count);

            _engine.Reset();
            _ = _engine.ExecuteTestCaseStandard("call", manifestUpdate.Hash.ToArray(), "newContract", new Array());
            Assert.AreEqual(VMState.FAULT, _engine.State);

            // Create

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("create", script.finalNEF, manifest.ToJson().ToString());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            var item = result.Pop();

            Assert.IsTrue(item.Type == VM.Types.StackItemType.InteropInterface);
            var ledger = (item as InteropInterface).GetInterface <Ledger.ContractState>();

            Assert.AreEqual(manifest.Hash, ledger.ScriptHash);

            // Call & Update

            _engine.Reset();
            var args = new Array
            {
                scriptUpdate.finalNEF,
                manifestUpdate.ToJson().ToString()
            };

            result = _engine.ExecuteTestCaseStandard("call", manifest.Hash.ToArray(), "oldContract", args);
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(123, item.GetBigInteger());

            // Call Again

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", manifestUpdate.Hash.ToArray(), "newContract", new Array());
            Assert.AreEqual(VMState.HALT, _engine.State);
            Assert.AreEqual(1, result.Count);

            item = result.Pop();
            Assert.IsInstanceOfType(item, typeof(Integer));
            Assert.AreEqual(124, item.GetBigInteger());

            // Check again for failures

            _engine.Reset();
            result = _engine.ExecuteTestCaseStandard("call", manifest.Hash.ToArray(), "oldContract", new Array());
            Assert.AreEqual(VMState.FAULT, _engine.State);
            Assert.AreEqual(0, result.Count);
        }
예제 #27
0
        public void TestContract_Update()
        {
            var engine = GetEngine(false, true);
            var script = new byte[1024 * 1024 + 1];

            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse();

            string manifestStr = new string(new char[ContractManifest.MaxLength + 1]);

            script = new byte[] { 0x01 };
            engine.CurrentContext.EvaluationStack.Push(manifestStr);
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse();

            manifestStr = "";
            engine.CurrentContext.EvaluationStack.Push(manifestStr);
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse();

            var manifest = ContractManifest.CreateDefault(script.ToScriptHash());

            byte[]  privkey = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                                0x01,  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
            KeyPair key    = new KeyPair(privkey);
            ECPoint pubkey = key.PublicKey;

            byte[] signature = Crypto.Sign(script.ToScriptHash().ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray());
            manifest.Groups = new ContractGroup[]
            {
                new ContractGroup()
                {
                    PubKey    = pubkey,
                    Signature = signature
                }
            };
            var snapshot = Blockchain.Singleton.GetSnapshot();
            var state    = TestUtils.GetContract();

            state.Manifest.Features = ContractFeatures.HasStorage;
            var storageItem = new StorageItem
            {
                Value      = new byte[] { 0x01 },
                IsConstant = false
            };

            var storageKey = new StorageKey
            {
                ScriptHash = state.ScriptHash,
                Key        = new byte[] { 0x01 }
            };

            snapshot.Contracts.Add(state.ScriptHash, state);
            snapshot.Storages.Add(storageKey, storageItem);
            engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0);
            engine.LoadScript(state.Script);
            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeTrue();

            // Remove Storage flag with something stored

            state.Manifest.Features = ContractFeatures.NoProperty;
            snapshot.Contracts.Add(state.ScriptHash, state);
            snapshot.Storages.Add(storageKey, storageItem);

            engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0);
            engine.LoadScript(state.Script);
            engine.CurrentContext.EvaluationStack.Push(manifest.ToString());
            engine.CurrentContext.EvaluationStack.Push(script);
            InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse();
        }
예제 #28
0
        public async Task <object> DeployContract(string nefPath, string manifestPath = null, bool sendTx = false)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (nefPath.IsNull())
            {
                return(Error(ErrorCode.ParameterIsNull, "nefPath is empty."));
            }
            if (manifestPath.IsNull())
            {
                manifestPath = Path.ChangeExtension(nefPath, ".manifest.json");
            }
            // Read nef
            NefFile nefFile = ReadNefFile(nefPath);


            using var snapshot = Blockchain.Singleton.GetSnapshot();
            var oldContract = snapshot.Contracts.TryGet(nefFile.ScriptHash);

            if (oldContract != null)
            {
                return(Error(ErrorCode.ContractAlreadyExist));
            }
            // Read manifest
            ContractManifest manifest = ReadManifestFile(manifestPath);

            // Basic script checks
            await CheckBadOpcode(nefFile.Script);

            // Build script
            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitSysCall(InteropService.Contract.Create, nefFile.Script, manifest.ToJson().ToString());
            var script = sb.ToArray();

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(script);
            }
            catch (InvalidOperationException)
            {
                return(Error(ErrorCode.EngineFault));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            var result = new DeployResultModel
            {
                ContractHash = nefFile.ScriptHash,
                GasConsumed  = new BigDecimal(tx.SystemFee, NativeContract.GAS.Decimals)
            };

            if (sendTx)
            {
                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                result.TxId = tx.Hash;
            }
            return(result);
        }
예제 #29
0
        private static bool Contract_Update(ApplicationEngine engine)
        {
            if (engine.Trigger != TriggerType.Application)
            {
                return(false);
            }

            byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray();
            if (script.Length > 1024 * 1024)
            {
                return(false);
            }
            var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString();

            if (manifest.Length > ContractManifest.MaxLength)
            {
                return(false);
            }

            var contract = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash);

            if (contract is null)
            {
                return(false);
            }

            if (script.Length > 0)
            {
                UInt160 hash_new = script.ToScriptHash();
                if (hash_new.Equals(engine.CurrentScriptHash))
                {
                    return(false);
                }
                if (engine.Snapshot.Contracts.TryGet(hash_new) != null)
                {
                    return(false);
                }
                contract = new ContractState
                {
                    Script   = script,
                    Manifest = contract.Manifest
                };
                contract.Manifest.Abi.Hash = hash_new;
                engine.Snapshot.Contracts.Add(hash_new, contract);
                if (contract.HasStorage)
                {
                    foreach (var pair in engine.Snapshot.Storages.Find(engine.CurrentScriptHash.ToArray()).ToArray())
                    {
                        engine.Snapshot.Storages.Add(new StorageKey
                        {
                            ScriptHash = hash_new,
                            Key        = pair.Key.Key
                        }, new StorageItem
                        {
                            Value      = pair.Value.Value,
                            IsConstant = false
                        });
                    }
                }
                Contract_Destroy(engine);
            }
            if (manifest.Length > 0)
            {
                contract          = engine.Snapshot.Contracts.GetAndChange(contract.ScriptHash);
                contract.Manifest = ContractManifest.Parse(manifest);
                if (!contract.Manifest.IsValid(contract.ScriptHash))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #30
0
        private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, out UInt160 scriptHash)
        {
            if (string.IsNullOrEmpty(manifestFilePath))
            {
                manifestFilePath = Path.ChangeExtension(nefFilePath, ".manifest.json");
            }

            // Read manifest

            var info = new FileInfo(manifestFilePath);

            if (!info.Exists || info.Length >= Transaction.MaxTransactionSize)
            {
                throw new ArgumentException(nameof(manifestFilePath));
            }

            var manifest = ContractManifest.Parse(File.ReadAllBytes(manifestFilePath));

            // Read nef

            info = new FileInfo(nefFilePath);
            if (!info.Exists || info.Length >= Transaction.MaxTransactionSize)
            {
                throw new ArgumentException(nameof(nefFilePath));
            }

            NefFile file;

            using (var stream = new BinaryReader(File.OpenRead(nefFilePath), Encoding.UTF8, false))
            {
                file = stream.ReadSerializable <NefFile>();
            }

            // Basic script checks

            using (var engine = ApplicationEngine.Create(TriggerType.Application, null, null, 0, true))
            {
                var context = engine.LoadScript(file.Script);

                while (context.InstructionPointer <= context.Script.Length)
                {
                    // Check bad opcodes

                    var ci = context.CurrentInstruction;

                    if (ci == null || !Enum.IsDefined(typeof(OpCode), ci.OpCode))
                    {
                        throw new FormatException($"OpCode not found at {context.InstructionPointer}-{((byte)ci.OpCode).ToString("x2")}");
                    }

                    context.InstructionPointer += ci.Size;
                }
            }

            // Build script

            scriptHash = file.ScriptHash;
            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitSysCall(ApplicationEngine.System_Contract_Create, file.Script, manifest.ToJson().ToString());
                return(sb.ToArray());
            }
        }