Пример #1
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.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.Contract.Update).Should().BeFalse();

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

            var manifest = TestUtils.CreateDefaultManifest(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
                }
            };
            manifest.Features = ContractFeatures.HasStorage;
            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
            {
                Id  = state.Id,
                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.Contract.Update).Should().BeTrue();
            engine.Snapshot.Storages.Find(BitConverter.GetBytes(state.Id)).ToList().Count().Should().Be(1);
        }
Пример #2
0
 private string CreateKey(StorageKey key) => key.Key.StartsWith(_options.Prefix) ? key.ToString() : $"{_options.Prefix}:{key}".ToLower();
Пример #3
0
 public static void SaveState(StorageKey key, object value)
 {
     _userSettings[key.ToString()] = value;
 }
Пример #4
0
 public void TestSetup()
 {
     uut = new StorageKey();
 }
Пример #5
0
 /// <inheritdoc/>
 public void Set <T>(StorageKey key, T value)
 {
     _database.HashSetAsync(CreateKey(key), value.SerializeToRedis());
 }
Пример #6
0
 public override StorageItem GetStorageItem(StorageKey key)
 {
     throw new NotImplementedException();
 }
Пример #7
0
 protected override bool ContainsInternal(StorageKey key)
 {
     return(store.Contains(key.ToArray()));
 }
Пример #8
0
 protected override void UpdateInternal(StorageKey key, StorageItem value)
 {
     InnerDict[key] = new MyValue(value.Value);
 }
Пример #9
0
 public MyKey(StorageKey key)
 {
     Id  = key.Id;
     Key = key.Key;
 }
Пример #10
0
 protected override void AddInternal(StorageKey key, StorageItem value)
 {
     InnerDict.Add(key, new MyValue(value.Value));
 }
Пример #11
0
 protected override bool ContainsInternal(StorageKey key)
 {
     return(InnerDict.ContainsKey(key));
 }
Пример #12
0
 protected override void DeleteInternal(StorageKey key)
 {
     InnerDict.Remove(key);
 }
Пример #13
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);
        }
        public bool TrySetValue(StorageKey sk, short missSize, BinaryDataListRow value)
        {
            _levelZeroCache[sk] = value;

            return(true);
        }
Пример #15
0
 protected bool HasRulesStorageForModel(StorageKey key)
 {
     return Rules.ContainsKey(key);
 }
Пример #16
0
 protected abstract void DeleteInternal(StorageKey key);
Пример #17
0
        public void TestStorage_Put()
        {
            var engine = GetEngine(false, true);

            //CheckStorageContext fail
            var key            = new byte[] { 0x01 };
            var value          = new byte[] { 0x02 };
            var state          = TestUtils.GetContract();
            var storageContext = new StorageContext
            {
                Id         = state.Id,
                IsReadOnly = false
            };

            engine.Put(storageContext, key, value);

            //key.Length > MaxStorageKeySize
            key   = new byte[ApplicationEngine.MaxStorageKeySize + 1];
            value = new byte[] { 0x02 };
            Assert.ThrowsException <ArgumentException>(() => engine.Put(storageContext, key, value));

            //value.Length > MaxStorageValueSize
            key   = new byte[] { 0x01 };
            value = new byte[ushort.MaxValue + 1];
            Assert.ThrowsException <ArgumentException>(() => engine.Put(storageContext, key, value));

            //context.IsReadOnly
            key   = new byte[] { 0x01 };
            value = new byte[] { 0x02 };
            storageContext.IsReadOnly = true;
            Assert.ThrowsException <ArgumentException>(() => engine.Put(storageContext, key, value));

            //storage value is constant
            var snapshot = Blockchain.Singleton.GetSnapshot();

            var storageKey = new StorageKey
            {
                Id  = state.Id,
                Key = new byte[] { 0x01 }
            };
            var storageItem = new StorageItem
            {
                Value      = new byte[] { 0x01, 0x02, 0x03, 0x04 },
                IsConstant = true
            };

            snapshot.AddContract(state.Hash, state);
            snapshot.Storages.Add(storageKey, storageItem);
            engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot);
            engine.LoadScript(new byte[] { 0x01 });
            key   = new byte[] { 0x01 };
            value = new byte[] { 0x02 };
            storageContext.IsReadOnly = false;
            Assert.ThrowsException <InvalidOperationException>(() => engine.Put(storageContext, key, value));

            //success
            storageItem.IsConstant = false;
            engine.Put(storageContext, key, value);

            //value length == 0
            key   = new byte[] { 0x01 };
            value = new byte[0];
            engine.Put(storageContext, key, value);
        }
Пример #18
0
 protected abstract bool ContainsInternal(StorageKey key);
Пример #19
0
 protected override void DeleteInternal(StorageKey key)
 {
     snapshot?.Delete(key.ToArray());
 }
Пример #20
0
 protected abstract StorageItem TryGetInternal(StorageKey key);
Пример #21
0
 protected override void UpdateInternal(StorageKey key, StorageItem value)
 {
     snapshot?.Put(key.ToArray(), value.ToArray());
 }
Пример #22
0
 protected abstract void AddInternal(StorageKey key, StorageItem value);
Пример #23
0
        /// <inheritdoc/>
        public void AddToList <T>(StorageKey key, T value)
        {
            var serializer = _options.Serializer ?? new JsonSerializer();

            _database.ListRightPushAsync(CreateKey(key), serializer.Serialize(value));
        }
Пример #24
0
        private void timer1_Tick(object sender, EventArgs e)
        {
            uint walletHeight = 0;

            if (Program.CurrentWallet != null)
            {
                walletHeight = (Program.CurrentWallet.WalletHeight > 0) ? Program.CurrentWallet.WalletHeight - 1 : 0;
            }

            lbl_height.Text = $"{walletHeight}/{Blockchain.Singleton.Height}/{Blockchain.Singleton.HeaderHeight}";

            lbl_count_node.Text = LocalNode.Singleton.ConnectedCount.ToString();
            TimeSpan persistence_span = DateTime.UtcNow - persistence_time;

            if (persistence_span < TimeSpan.Zero)
            {
                persistence_span = TimeSpan.Zero;
            }
            if (persistence_span > Blockchain.TimePerBlock)
            {
                toolStripProgressBar1.Style = ProgressBarStyle.Marquee;
            }
            else
            {
                toolStripProgressBar1.Value = persistence_span.Seconds;
                toolStripProgressBar1.Style = ProgressBarStyle.Blocks;
            }
            if (Program.CurrentWallet != null)
            {
                if (Program.CurrentWallet.WalletHeight <= Blockchain.Singleton.Height + 1)
                {
                    if (balance_changed)
                    {
                        using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
                        {
                            IEnumerable <Coin> coins             = Program.CurrentWallet?.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent)) ?? Enumerable.Empty <Coin>();
                            Fixed8             bonus_available   = snapshot.CalculateBonus(Program.CurrentWallet.GetUnclaimedCoins().Select(p => p.Reference));
                            Fixed8             bonus_unavailable = snapshot.CalculateBonus(coins.Where(p => p.State.HasFlag(CoinState.Confirmed) && p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).Select(p => p.Reference), snapshot.Height + 1);
                            Fixed8             bonus             = bonus_available + bonus_unavailable;
                            var assets = coins.GroupBy(p => p.Output.AssetId, (k, g) => new
                            {
                                Asset = snapshot.Assets.TryGet(k),
                                Value = g.Sum(p => p.Output.Value),
                                Claim = k.Equals(Blockchain.UtilityToken.Hash) ? bonus : Fixed8.Zero
                            }).ToDictionary(p => p.Asset.AssetId);
                            if (bonus != Fixed8.Zero && !assets.ContainsKey(Blockchain.UtilityToken.Hash))
                            {
                                assets[Blockchain.UtilityToken.Hash] = new
                                {
                                    Asset = snapshot.Assets.TryGet(Blockchain.UtilityToken.Hash),
                                    Value = Fixed8.Zero,
                                    Claim = bonus
                                };
                            }
                            var balance_ans = coins.Where(p => p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).GroupBy(p => p.Output.ScriptHash).ToDictionary(p => p.Key, p => p.Sum(i => i.Output.Value));
                            var balance_anc = coins.Where(p => p.Output.AssetId.Equals(Blockchain.UtilityToken.Hash)).GroupBy(p => p.Output.ScriptHash).ToDictionary(p => p.Key, p => p.Sum(i => i.Output.Value));
                            foreach (ListViewItem item in listView1.Items)
                            {
                                UInt160 script_hash = item.Name.ToScriptHash();
                                Fixed8  ans         = balance_ans.ContainsKey(script_hash) ? balance_ans[script_hash] : Fixed8.Zero;
                                Fixed8  anc         = balance_anc.ContainsKey(script_hash) ? balance_anc[script_hash] : Fixed8.Zero;
                                item.SubItems["ans"].Text = ans.ToString();
                                item.SubItems["anc"].Text = anc.ToString();
                            }
                            foreach (AssetState asset in listView2.Items.OfType <ListViewItem>().Select(p => p.Tag as AssetState).Where(p => p != null).ToArray())
                            {
                                if (!assets.ContainsKey(asset.AssetId))
                                {
                                    listView2.Items.RemoveByKey(asset.AssetId.ToString());
                                }
                            }
                            foreach (var asset in assets.Values)
                            {
                                string value_text = asset.Value.ToString() + (asset.Asset.AssetId.Equals(Blockchain.UtilityToken.Hash) ? $"+({asset.Claim})" : "");
                                if (listView2.Items.ContainsKey(asset.Asset.AssetId.ToString()))
                                {
                                    listView2.Items[asset.Asset.AssetId.ToString()].SubItems["value"].Text = value_text;
                                }
                                else
                                {
                                    string asset_name = asset.Asset.AssetType == AssetType.GoverningToken ? "NEO" :
                                                        asset.Asset.AssetType == AssetType.UtilityToken ? "NeoGas" :
                                                        asset.Asset.GetName();
                                    listView2.Items.Add(new ListViewItem(new[]
                                    {
                                        new ListViewItem.ListViewSubItem
                                        {
                                            Name = "name",
                                            Text = asset_name
                                        },
                                        new ListViewItem.ListViewSubItem
                                        {
                                            Name = "type",
                                            Text = asset.Asset.AssetType.ToString()
                                        },
                                        new ListViewItem.ListViewSubItem
                                        {
                                            Name = "value",
                                            Text = value_text
                                        },
                                        new ListViewItem.ListViewSubItem
                                        {
                                            ForeColor = Color.Gray,
                                            Name      = "issuer",
                                            Text      = $"{Strings.UnknownIssuer}[{asset.Asset.Owner}]"
                                        }
                                    }, -1, listView2.Groups["unchecked"])
                                    {
                                        Name = asset.Asset.AssetId.ToString(),
                                        Tag  = asset.Asset,
                                        UseItemStyleForSubItems = false
                                    });
                                }
                            }
                            balance_changed = false;
                        }
                    }
                    foreach (ListViewItem item in listView2.Groups["unchecked"].Items.OfType <ListViewItem>().ToArray())
                    {
                        ListViewItem.ListViewSubItem subitem = item.SubItems["issuer"];
                        AssetState             asset         = (AssetState)item.Tag;
                        CertificateQueryResult result;
                        if (asset.AssetType == AssetType.GoverningToken || asset.AssetType == AssetType.UtilityToken)
                        {
                            result = new CertificateQueryResult {
                                Type = CertificateQueryResultType.System
                            };
                        }
                        else
                        {
                            result = CertificateQueryService.Query(asset.Owner);
                        }
                        using (result)
                        {
                            subitem.Tag = result.Type;
                            switch (result.Type)
                            {
                            case CertificateQueryResultType.Querying:
                            case CertificateQueryResultType.QueryFailed:
                                break;

                            case CertificateQueryResultType.System:
                                subitem.ForeColor = Color.Green;
                                subitem.Text      = Strings.SystemIssuer;
                                break;

                            case CertificateQueryResultType.Invalid:
                                subitem.ForeColor = Color.Red;
                                subitem.Text      = $"[{Strings.InvalidCertificate}][{asset.Owner}]";
                                break;

                            case CertificateQueryResultType.Expired:
                                subitem.ForeColor = Color.Yellow;
                                subitem.Text      = $"[{Strings.ExpiredCertificate}]{result.Certificate.Subject}[{asset.Owner}]";
                                break;

                            case CertificateQueryResultType.Good:
                                subitem.ForeColor = Color.Black;
                                subitem.Text      = $"{result.Certificate.Subject}[{asset.Owner}]";
                                break;
                            }
                            switch (result.Type)
                            {
                            case CertificateQueryResultType.System:
                            case CertificateQueryResultType.Missing:
                            case CertificateQueryResultType.Invalid:
                            case CertificateQueryResultType.Expired:
                            case CertificateQueryResultType.Good:
                                item.Group = listView2.Groups["checked"];
                                break;
                            }
                        }
                    }
                }
                if (check_nep5_balance && persistence_span > TimeSpan.FromSeconds(2))
                {
                    UInt160[] addresses = Program.CurrentWallet.GetAccounts().Select(p => p.ScriptHash).ToArray();
                    foreach (string s in Settings.Default.NEP5Watched)
                    {
                        UInt160 script_hash = UInt160.Parse(s);
                        byte[]  script;
                        using (ScriptBuilder sb = new ScriptBuilder())
                        {
                            sb.EmitAppCall(script_hash, "decimals");
                            sb.EmitAppCall(script_hash, "name");
                            script = sb.ToArray();
                        }
                        ApplicationEngine engine = ApplicationEngine.Run(script);
                        if (engine.State.HasFlag(VMState.FAULT))
                        {
                            continue;
                        }
                        string name     = engine.ResultStack.Pop().GetString();
                        byte   decimals = (byte)engine.ResultStack.Pop().GetBigInteger();

                        BigInteger amount = BigInteger.Zero;
                        using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
                        {
                            ContractState asset = snapshot.Contracts.TryGet(script_hash);
                            foreach (UInt160 address in addresses)
                            {
                                StorageKey key = new StorageKey
                                {
                                    ScriptHash = asset.ScriptHash,
                                    Key        = address.ToArray()
                                };
                                StorageItem item = snapshot.Storages.TryGet(key);
                                if (item != null)
                                {
                                    amount += new BigInteger(item.Value);
                                }
                            }
                        }
                        if (amount == 0)
                        {
                            listView2.Items.RemoveByKey(script_hash.ToString());
                            continue;
                        }
                        BigDecimal balance    = new BigDecimal(amount, decimals);
                        string     value_text = balance.ToString();
                        if (listView2.Items.ContainsKey(script_hash.ToString()))
                        {
                            listView2.Items[script_hash.ToString()].SubItems["value"].Text = value_text;
                        }
                        else
                        {
                            listView2.Items.Add(new ListViewItem(new[]
                            {
                                new ListViewItem.ListViewSubItem
                                {
                                    Name = "name",
                                    Text = name
                                },
                                new ListViewItem.ListViewSubItem
                                {
                                    Name = "type",
                                    Text = "NEP-5"
                                },
                                new ListViewItem.ListViewSubItem
                                {
                                    Name = "value",
                                    Text = value_text
                                },
                                new ListViewItem.ListViewSubItem
                                {
                                    ForeColor = Color.Gray,
                                    Name      = "issuer",
                                    Text      = $"ScriptHash:{script_hash}"
                                }
                            }, -1, listView2.Groups["checked"])
                            {
                                Name = script_hash.ToString(),
                                UseItemStyleForSubItems = false
                            });
                        }
                    }
                    check_nep5_balance = false;
                }
            }
        }
Пример #25
0
        /// <inheritdoc/>
        public T Get <T>(StorageKey key)
        {
            var hash = _database.HashGetAll(CreateKey(key));

            return(hash.DeserializeRedis <T>());
        }
Пример #26
0
        public void TestStorage_Put()
        {
            var engine = GetEngine(false, true);

            engine.CurrentContext.EvaluationStack.Push(1);
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse();

            //CheckStorageContext fail
            var key   = new byte[] { 0x01 };
            var value = new byte[] { 0x02 };

            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            var state          = TestUtils.GetContract();
            var storageContext = new StorageContext
            {
                Id         = state.Id,
                IsReadOnly = false
            };

            engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext));
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeTrue();

            //key.Length > MaxStorageKeySize
            key   = new byte[InteropService.Storage.MaxKeySize + 1];
            value = new byte[] { 0x02 };
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext));
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse();

            //value.Length > MaxStorageValueSize
            key   = new byte[] { 0x01 };
            value = new byte[ushort.MaxValue + 1];
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext));
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse();

            //context.IsReadOnly
            key   = new byte[] { 0x01 };
            value = new byte[] { 0x02 };
            storageContext.IsReadOnly = true;
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext));
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse();

            //storage value is constant
            var snapshot = Blockchain.Singleton.GetSnapshot();

            state.Manifest.Features = ContractFeatures.HasStorage;

            var storageKey = new StorageKey
            {
                Id  = state.Id,
                Key = new byte[] { 0x01 }
            };
            var storageItem = new StorageItem
            {
                Value      = new byte[] { 0x01, 0x02, 0x03, 0x04 },
                IsConstant = true
            };

            snapshot.Contracts.Add(state.ScriptHash, state);
            snapshot.Storages.Add(storageKey, storageItem);
            engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0);
            engine.LoadScript(new byte[] { 0x01 });
            key   = new byte[] { 0x01 };
            value = new byte[] { 0x02 };
            storageContext.IsReadOnly = false;
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext));
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse();

            //success
            storageItem.IsConstant = false;
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext));
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeTrue();

            //value length == 0
            key   = new byte[] { 0x01 };
            value = new byte[0];
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext));
            InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeTrue();
        }
Пример #27
0
        protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount)
        {
            if (amount.Sign < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(amount));
            }
            if (!from.Equals(engine.CallingScriptHash) && !InteropService.Runtime.CheckWitnessInternal(engine, from))
            {
                return(false);
            }
            ContractState contract_to = engine.Snapshot.Contracts.TryGet(to);

            if (contract_to?.Payable == false)
            {
                return(false);
            }
            StorageKey  key_from     = CreateAccountKey(from);
            StorageItem storage_from = engine.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.Snapshot.Storages.Delete(key_from);
                    }
                    else
                    {
                        state_from.Balance -= amount;
                        storage_from        = engine.Snapshot.Storages.GetAndChange(key_from);
                        storage_from.Value  = state_from.ToByteArray();
                    }
                    StorageKey  key_to     = CreateAccountKey(to);
                    StorageItem storage_to = engine.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.SendNotification(Hash, new Array(new StackItem[] { "Transfer", from.ToArray(), to.ToArray(), amount }));
            return(true);
        }
Пример #28
0
        protected void OnConvertCommand(string[] args)
        {
            // TODO, could actually run in a background thread, with updates written out to console.
            // TODO2, not necessary, it's a one time thing...

            // TODO ugly quickfix, add additional command handler to support commands with multiple args
            string fileStoragePath  = null;
            string dbStoragePath    = null;
            string verificationPath = null;
            int    includeArchives  = 0;

            if (args.Length == 2)
            {
                fileStoragePath = args[0];
                dbStoragePath   = args[1];
            }
            else if (args.Length == 3)
            {
                fileStoragePath  = args[0];
                dbStoragePath    = args[1];
                verificationPath = args[2];
            }
            else if (args.Length == 4)
            {
                fileStoragePath  = args[0];
                dbStoragePath    = args[1];
                verificationPath = args[2];
                includeArchives  = Int32.Parse(args[3]);
            }

            Func <string, IKeyValueStoreAdapter> fileStorageFactory = (name)
                                                                      => new BasicDiskStore(fileStoragePath);

            Func <string, IKeyValueStoreAdapter> dbStorageFactory = (name)
                                                                    => new DBPartition(Spook.Logger, dbStoragePath);

            Func <string, IKeyValueStoreAdapter> verificationStorageFactory = null;

            if (!string.IsNullOrEmpty(verificationPath))
            {
                verificationStorageFactory = (name) => new BasicDiskStore(verificationPath);
            }

            KeyValueStore <Hash, Archive> fileStorageArchives = null;

            if (includeArchives > 0)
            {
                fileStorageArchives = new KeyValueStore <Hash, Archive>(fileStorageFactory("archives"));
            }

            KeyValueStore <Hash, byte[]> fileStorageContents = new KeyValueStore <Hash, byte[]>(fileStorageFactory("contents"));
            KeyStoreStorage fileStorageRoot = new KeyStoreStorage(fileStorageFactory("chain.main"));

            KeyValueStore <Hash, Archive> dbStorageArchives = new KeyValueStore <Hash, Archive>(dbStorageFactory("archives"));
            KeyValueStore <Hash, byte[]>  dbStorageContents = new KeyValueStore <Hash, byte[]>(dbStorageFactory("contents"));
            KeyStoreStorage dbStorageRoot = new KeyStoreStorage(dbStorageFactory("chain.main"));

            KeyValueStore <Hash, Archive> fileStorageArchiveVerify = new KeyValueStore <Hash, Archive>(verificationStorageFactory("archives.verify"));
            KeyValueStore <Hash, byte[]>  fileStorageContentVerify = new KeyValueStore <Hash, byte[]>(verificationStorageFactory("contents.verify"));
            KeyStoreStorage fileStorageRootVerify = new KeyStoreStorage(verificationStorageFactory("chain.main.verify"));

            int count = 0;

            if (includeArchives > 0)
            {
                Spook.Logger.Message("Starting copying archives...");
                fileStorageArchives.Visit((key, value) =>
                {
                    count++;
                    dbStorageArchives.Set(key, value);
                    var val = dbStorageArchives.Get(key);
                    if (!CompareArchive(val, value))
                    {
                        Spook.Logger.Message($"Archives: NewValue: {value.Hash} and oldValue: {val.Hash} differ, fail now!");
                        Environment.Exit(-1);
                    }
                });
                Spook.Logger.Message($"Finished copying {count} archives...");
                count = 0;
            }

            Spook.Logger.Message("Starting copying content items...");
            fileStorageContents.Visit((key, value) =>
            {
                count++;
                dbStorageContents.Set(key, value);
                var val = dbStorageContents.Get(key);
                Spook.Logger.Message("COUNT: " + count);
                if (!CompareBA(val, value))
                {
                    Spook.Logger.Message($"CONTENTS: NewValue: {Encoding.UTF8.GetString(val)} and oldValue: {Encoding.UTF8.GetString(value)} differ, fail now!");
                    Environment.Exit(-1);
                }
            });

            Spook.Logger.Message("Starting copying root...");
            fileStorageRoot.Visit((key, value) =>
            {
                count++;
                StorageKey stKey = new StorageKey(key);
                dbStorageRoot.Put(stKey, value);
                Spook.Logger.Message("COUNT: " + count);
                var val = dbStorageRoot.Get(stKey);
                if (!CompareBA(val, value))
                {
                    Spook.Logger.Message($"ROOT: NewValue: {Encoding.UTF8.GetString(val)} and oldValue: {Encoding.UTF8.GetString(value)} differ, fail now!");
                    Environment.Exit(-1);
                }
            });
            Spook.Logger.Message($"Finished copying {count} root items...");
            count = 0;

            if (!string.IsNullOrEmpty(verificationPath))
            {
                Spook.Logger.Message($"Create verification stores");

                if (includeArchives > 0)
                {
                    Spook.Logger.Message("Start writing verify archives...");
                    dbStorageArchives.Visit((key, value) =>
                    {
                        count++;
                        // very ugly and might not always work, but should be ok for now
                        byte[] bytes = value.Size.ToUnsignedByteArray();
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(bytes);
                        }
                        int size = BitConverter.ToInt32(bytes, 0);

                        var ms = new MemoryStream(new byte[size]);
                        var bw = new BinaryWriter(ms);
                        value.SerializeData(bw);
                        fileStorageContentVerify.Set(key, ms.ToArray());
                    });
                    Spook.Logger.Message($"Finished writing {count} archives...");
                    count = 0;
                }

                Spook.Logger.Message("Start writing content items...");
                dbStorageContents.Visit((key, value) =>
                {
                    count++;
                    Spook.Logger.Message($"Content: {count}");
                    fileStorageContentVerify.Set(key, value);
                });
                Spook.Logger.Message($"Finished writing {count} content items...");
                count = 0;

                Spook.Logger.Message("Starting writing root...");
                dbStorageRoot.Visit((key, value) =>
                {
                    count++;
                    StorageKey stKey = new StorageKey(key);
                    fileStorageRootVerify.Put(stKey, value);
                    Spook.Logger.Message($"Wrote: {count}");
                });
                Spook.Logger.Message($"Finished writing {count} root items...");
            }
        }
Пример #29
0
        public void TestStorage_Put()
        {
            var engine = GetEngine(false, true);

            engine.CurrentContext.EvaluationStack.Push(1);
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse();

            //CheckStorageContext fail
            var key   = new byte[] { 0x01 };
            var value = new byte[] { 0x02 };

            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            var state          = TestUtils.GetContract();
            var storageContext = new StorageContext
            {
                ScriptHash = state.ScriptHash,
                IsReadOnly = false
            };

            engine.CurrentContext.EvaluationStack.Push(new InteropInterface <StorageContext>(storageContext));
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse();

            //key.Length > MaxStorageKeySize
            key   = new byte[InteropService.MaxStorageKeySize + 1];
            value = new byte[] { 0x02 };
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface <StorageContext>(storageContext));
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse();

            //value.Length > MaxStorageValueSize
            key   = new byte[] { 0x01 };
            value = new byte[ushort.MaxValue + 1];
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface <StorageContext>(storageContext));
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse();

            //context.IsReadOnly
            key   = new byte[] { 0x01 };
            value = new byte[] { 0x02 };
            storageContext.IsReadOnly = true;
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface <StorageContext>(storageContext));
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse();

            //storage value is constant
            var mockSnapshot = new Mock <Snapshot>();

            state.Manifest.Features = ContractFeatures.HasStorage;

            var storageKey = new StorageKey
            {
                ScriptHash = state.ScriptHash,
                Key        = new byte[] { 0x01 }
            };
            var storageItem = new StorageItem
            {
                Value      = new byte[] { 0x01, 0x02, 0x03, 0x04 },
                IsConstant = true
            };

            mockSnapshot.SetupGet(p => p.Contracts).Returns(new TestDataCache <UInt160, ContractState>(state.ScriptHash, state));
            mockSnapshot.SetupGet(p => p.Storages).Returns(new TestDataCache <StorageKey, StorageItem>(storageKey, storageItem));
            engine = new ApplicationEngine(TriggerType.Application, null, mockSnapshot.Object, 0);
            engine.LoadScript(new byte[] { 0x01 });
            key   = new byte[] { 0x01 };
            value = new byte[] { 0x02 };
            storageContext.IsReadOnly = false;
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface <StorageContext>(storageContext));
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse();

            //success
            storageItem.IsConstant = false;
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface <StorageContext>(storageContext));
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeTrue();

            //value length == 0
            key   = new byte[] { 0x01 };
            value = new byte[0];
            engine.CurrentContext.EvaluationStack.Push(value);
            engine.CurrentContext.EvaluationStack.Push(key);
            engine.CurrentContext.EvaluationStack.Push(new InteropInterface <StorageContext>(storageContext));
            InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeTrue();
        }
Пример #30
0
 public static string BuildStateStorageKey(this StorageKey key)
 {
     return(DataEntryPrefix.StStorage.BuildKey(key.ScriptHash.ToArray().Concat(key.Key).ToString()));
 }
Пример #31
0
 public override StorageItem GetStorageItem(StorageKey key)
 {
     return(db.TryGet <StorageItem>(ReadOptions.Default, DataEntryPrefix.ST_Storage, key));
 }
Пример #32
0
        protected HashSet<StorageValue> GetRulesStorageForModel(StorageKey key)
        {
            if (!HasRulesStorageForModel(key))
            {
                Rules.Add(key, new HashSet<StorageValue>());
            }

            return Rules[key];
        }