Example #1
0
        User DowngradeDelegate(Data.Models.Delegate delegat)
        {
            var user = new User
            {
                Address         = delegat.Address,
                FirstLevel      = delegat.FirstLevel,
                LastLevel       = delegat.LastLevel,
                Balance         = delegat.Balance,
                Counter         = delegat.Counter,
                Delegate        = null,
                DelegateId      = null,
                DelegationLevel = null,
                Id                = delegat.Id,
                Activated         = delegat.Activated,
                DelegationsCount  = delegat.DelegationsCount,
                OriginationsCount = delegat.OriginationsCount,
                TransactionsCount = delegat.TransactionsCount,
                RevealsCount      = delegat.RevealsCount,
                ContractsCount    = delegat.ContractsCount,
                MigrationsCount   = delegat.MigrationsCount,
                PublicKey         = delegat.PublicKey,
                Revealed          = delegat.Revealed,
                Staked            = false,
                Type              = AccountType.User,
            };

            Db.Entry(delegat).State = EntityState.Detached;
            Db.Entry(user).State    = EntityState.Modified;
            Cache.Accounts.Add(user);

            return(user);
        }
Example #2
0
        Task <Data.Models.Delegate> UpgradeUser(User user, int level, Protocol proto)
        {
            var delegat = new Data.Models.Delegate
            {
                ActivationLevel   = level,
                Address           = user.Address,
                FirstLevel        = user.FirstLevel,
                LastLevel         = user.LastLevel,
                Balance           = user.Balance,
                Counter           = user.Counter,
                DeactivationLevel = GracePeriod.Init(level, proto.BlocksPerCycle, proto.PreservedCycles),
                Delegate          = null,
                DelegateId        = null,
                DelegationLevel   = null,
                Id                = user.Id,
                Activated         = user.Activated,
                DelegationsCount  = user.DelegationsCount,
                OriginationsCount = user.OriginationsCount,
                TransactionsCount = user.TransactionsCount,
                RevealsCount      = user.RevealsCount,
                ContractsCount    = user.ContractsCount,
                MigrationsCount   = user.MigrationsCount,
                PublicKey         = user.PublicKey,
                Revealed          = user.Revealed,
                Staked            = true,
                StakingBalance    = user.Balance,
                Type              = AccountType.Delegate,
            };

            Db.Entry(user).State    = EntityState.Detached;
            Db.Entry(delegat).State = EntityState.Modified;
            Cache.Accounts.Add(delegat);

            return(Task.FromResult(delegat));
        }
Example #3
0
 protected virtual void TestDelegatorsCount(JsonElement remote, Data.Models.Delegate local)
 {
     if (remote.RequiredArray("delegated_contracts").Count() != local.DelegatorsCount)
     {
         throw new Exception($"Diagnostics failed: wrong delegators count {local.Address}");
     }
 }
Example #4
0
        protected override void TestDelegatorsCount(JsonElement remote, Data.Models.Delegate local)
        {
            var delegators = remote.RequiredArray("delegated_contracts").Count();

            if (delegators != local.DelegatorsCount && delegators != local.DelegatorsCount + 1)
            {
                throw new Exception($"Diagnostics failed: wrong delegators count {local.Address}");
            }
        }
Example #5
0
        async Task UpdateDelegate(Data.Models.Delegate delegat, bool staked)
        {
            delegat.Staked = staked;

            foreach (var delegator in await Db.Accounts.Where(x => x.DelegateId == delegat.Id).ToListAsync())
            {
                Cache.Accounts.Add(delegator);
                Db.TryAttach(delegator);

                delegator.Staked = staked;
            }
        }
Example #6
0
        protected virtual async Task TestDelegate(int level, Data.Models.Delegate delegat, Protocol proto)
        {
            var remote = await Rpc.GetDelegateAsync(level, delegat.Address);

            if (remote.RequiredInt64("balance") != delegat.Balance)
            {
                throw new Exception($"Diagnostics failed: wrong balance {delegat.Address}");
            }

            if (remote.RequiredBool("deactivated") != !delegat.Staked)
            {
                throw new Exception($"Diagnostics failed: wrong delegate state {delegat.Address}");
            }

            var deactivationCycle = (delegat.DeactivationLevel - 1) >= proto.FirstLevel
                ? proto.GetCycle(delegat.DeactivationLevel - 1)
                : (await Cache.Blocks.GetAsync(delegat.DeactivationLevel - 1)).Cycle;

            if (remote.RequiredInt32("grace_period") != deactivationCycle)
            {
                throw new Exception($"Diagnostics failed: wrong delegate grace period {delegat.Address}");
            }

            if (remote.RequiredInt64("staking_balance") != delegat.StakingBalance)
            {
                throw new Exception($"Diagnostics failed: wrong staking balance {delegat.Address}");
            }

            var frozenBalances = remote.RequiredArray("frozen_balance_by_cycle").EnumerateArray();

            if ((frozenBalances.Any() ? frozenBalances.Sum(x => GetDeposits(x)) : 0) != delegat.FrozenDeposits)
            {
                throw new Exception($"Diagnostics failed: wrong frozen deposits {delegat.Address}");
            }

            if ((frozenBalances.Any() ? frozenBalances.Sum(x => x.RequiredInt64("rewards")) : 0) != delegat.FrozenRewards)
            {
                throw new Exception($"Diagnostics failed: wrong frozen rewards {delegat.Address}");
            }

            if ((frozenBalances.Any() ? frozenBalances.Sum(x => x.RequiredInt64("fees")) : 0) != delegat.FrozenFees)
            {
                throw new Exception($"Diagnostics failed: wrong frozen fees {delegat.Address}");
            }

            TestDelegatorsCount(remote, delegat);
        }
Example #7
0
        async Task TestDelegate(int level, Data.Models.Delegate delegat, Protocol proto)
        {
            var remote = await GetRemoteDelegate(level, delegat.Address);

            if (remote.Balance != delegat.Balance)
            {
                throw new Exception($"Diagnostics failed: wrong balance {delegat.Address}");
            }

            if (remote.Deactivated != !delegat.Staked)
            {
                throw new Exception($"Diagnostics failed: wrong delegate state {delegat.Address}");
            }

            if (remote.GracePeriod != (delegat.DeactivationLevel - 2) / proto.BlocksPerCycle)
            {
                throw new Exception($"Diagnostics failed: wrong delegate grace period {delegat.Address}");
            }

            if (remote.Delegators.Count != delegat.DelegatorsCount)
            {
                throw new Exception($"Diagnostics failed: wrong delegators count {delegat.Address}");
            }

            if ((remote.FrozenBalances.Count > 0 ? remote.FrozenBalances.Sum(x => x.Deposit) : 0) != delegat.FrozenDeposits)
            {
                throw new Exception($"Diagnostics failed: wrong frozen deposits {delegat.Address}");
            }

            if ((remote.FrozenBalances.Count > 0 ? remote.FrozenBalances.Sum(x => x.Fees) : 0) != delegat.FrozenFees)
            {
                throw new Exception($"Diagnostics failed: wrong frozen fees {delegat.Address}");
            }

            if ((remote.FrozenBalances.Count > 0 ? remote.FrozenBalances.Sum(x => x.Rewards) : 0) != delegat.FrozenRewards)
            {
                throw new Exception($"Diagnostics failed: wrong frozen rewards {delegat.Address}");
            }

            if (remote.StakingBalance != delegat.StakingBalance)
            {
                throw new Exception($"Diagnostics failed: wrong staking balance {delegat.Address}");
            }
        }
Example #8
0
        public async Task Init(Block block, RawBlock rawBlock)
        {
            var protocol = await Cache.Protocols.GetAsync(rawBlock.Protocol);

            BootstrapedAccounts = new List <Account>(65);
            Timestamp           = rawBlock.Header.Timestamp;
            Level = rawBlock.Level;
            Block = block;

            var stream = await Proto.Node.GetContractsAsync(level : 1);

            var contracts = await(Proto.Serializer as Serializer).DeserializeContracts(stream);
            var delegates = new List <Data.Models.Delegate>(8);

            #region bootstrap delegates
            foreach (var data in contracts.Where(x => x.Delegate == x.Address))
            {
                var baker = new Data.Models.Delegate
                {
                    Id                = Cache.AppState.NextAccountId(),
                    Address           = data.Address,
                    FirstLevel        = rawBlock.Level,
                    LastLevel         = rawBlock.Level,
                    ActivationLevel   = 1,
                    DeactivationLevel = GracePeriod.Init(1, protocol.BlocksPerCycle, protocol.PreservedCycles),
                    Balance           = data.Balance,
                    Counter           = data.Counter,
                    PublicKey         = data.Manager,
                    Staked            = true,
                    Revealed          = true,
                    Type              = AccountType.Delegate
                };
                Cache.Accounts.Add(baker);
                BootstrapedAccounts.Add(baker);
                delegates.Add(baker);
            }
            #endregion

            #region bootstrap users
            foreach (var data in contracts.Where(x => x.Address[0] == 't' && String.IsNullOrEmpty(x.Delegate)))
            {
                var user = new User
                {
                    Id         = Cache.AppState.NextAccountId(),
                    Address    = data.Address,
                    FirstLevel = rawBlock.Level,
                    LastLevel  = rawBlock.Level,
                    Balance    = data.Balance,
                    Counter    = data.Counter,
                    Type       = AccountType.User
                };
                Cache.Accounts.Add(user);
                BootstrapedAccounts.Add(user);
            }
            #endregion

            #region bootstrap contracts
            foreach (var data in contracts.Where(x => x.Address[0] == 'K'))
            {
                var manager = (User)await Cache.Accounts.GetAsync(data.Manager);

                manager.ContractsCount++;

                var contract = new Contract
                {
                    Id              = Cache.AppState.NextAccountId(),
                    Address         = data.Address,
                    FirstLevel      = rawBlock.Level,
                    LastLevel       = rawBlock.Level,
                    Balance         = data.Balance,
                    Counter         = data.Counter,
                    Spendable       = false,
                    DelegationLevel = 1,
                    Delegate        = Cache.Accounts.GetDelegate(data.Delegate),
                    Manager         = manager,
                    Staked          = !String.IsNullOrEmpty(data.Delegate),
                    Type            = AccountType.Contract,
                    Kind            = ContractKind.SmartContract,
                };

                Cache.Accounts.Add(contract);
                BootstrapedAccounts.Add(contract);
            }
            #endregion

            #region stats
            foreach (var baker in delegates)
            {
                var delegators = BootstrapedAccounts.Where(x => x.Delegate == baker);

                baker.DelegatorsCount = delegators.Count();
                baker.StakingBalance  = baker.Balance
                                        + (baker.DelegatorsCount > 0 ? delegators.Sum(x => x.Balance) : 0);
            }
            #endregion
        }
Example #9
0
        async Task <List <Account> > BootstrapAccounts(Protocol protocol, JToken parameters)
        {
            var bootstrapAccounts = parameters["bootstrap_accounts"]?
                                    .Select(x => (x[0].Value <string>(), x[1].Value <long>()))
                                    .ToList() ?? new(0);

            var bootstrapContracts = parameters["bootstrap_contracts"]?
                                     .Select(x =>
                                             (
                                                 x["amount"].Value <long>(),
                                                 x["delegate"]?.Value <string>() ?? null,
                                                 x["script"]["code"].ToString(),
                                                 x["script"]["storage"].ToString())
                                             )
                                     .ToList() ?? new(0);

            var accounts = new List <Account>(bootstrapAccounts.Count + bootstrapContracts.Count);

            #region allocate null-address
            var nullAddress = (User)await Cache.Accounts.GetAsync(NullAddress.Address);

            if (nullAddress.Id != NullAddress.Id)
            {
                throw new Exception("Failed to allocate null-address");
            }
            #endregion

            #region bootstrap delegates
            foreach (var(pubKey, balance) in bootstrapAccounts.Where(x => x.Item1[0] != 't'))
            {
                var baker = new Data.Models.Delegate
                {
                    Id                = Cache.AppState.NextAccountId(),
                    Address           = PubKey.FromBase58(pubKey).Address,
                    Balance           = balance,
                    StakingBalance    = balance,
                    Counter           = 0,
                    PublicKey         = pubKey,
                    FirstLevel        = 1,
                    LastLevel         = 1,
                    ActivationLevel   = 1,
                    DeactivationLevel = GracePeriod.Init(2, protocol),
                    Staked            = true,
                    Revealed          = true,
                    Type              = AccountType.Delegate
                };
                Cache.Accounts.Add(baker);
                accounts.Add(baker);
            }
            #endregion

            #region bootstrap users
            foreach (var(pkh, balance) in bootstrapAccounts.Where(x => x.Item1[0] == 't'))
            {
                var user = new User
                {
                    Id         = Cache.AppState.NextAccountId(),
                    Address    = pkh,
                    Balance    = balance,
                    Counter    = 0,
                    FirstLevel = 1,
                    LastLevel  = 1,
                    Type       = AccountType.User
                };
                Cache.Accounts.Add(user);
                accounts.Add(user);
            }
            #endregion

            #region bootstrap contracts
            var index = 0;
            foreach (var(balance, delegatePkh, codeStr, storageStr) in bootstrapContracts)
            {
                #region contract
                var delegat = Cache.Accounts.GetDelegate(delegatePkh);
                var manager = nullAddress;

                var contract = new Contract
                {
                    Id              = Cache.AppState.NextAccountId(),
                    Address         = OriginationNonce.GetContractAddress(index++),
                    Balance         = balance,
                    Counter         = 0,
                    FirstLevel      = 1,
                    LastLevel       = 1,
                    Spendable       = false,
                    DelegationLevel = delegat == null ? null : 1,
                    Delegate        = delegat,
                    Manager         = manager,
                    Staked          = delegat != null,
                    Type            = AccountType.Contract,
                    Kind            = ContractKind.SmartContract,
                };

                manager.ContractsCount++;
                if (delegat != null)
                {
                    delegat.DelegatorsCount++;
                    delegat.StakingBalance += contract.Balance;
                }

                Cache.Accounts.Add(contract);
                accounts.Add(contract);
                #endregion

                #region script
                var code           = Micheline.FromJson(codeStr) as MichelineArray;
                var micheParameter = code.First(x => x is MichelinePrim p && p.Prim == PrimType.parameter);
                var micheStorage   = code.First(x => x is MichelinePrim p && p.Prim == PrimType.storage);
                var micheCode      = code.First(x => x is MichelinePrim p && p.Prim == PrimType.code);
                var micheViews     = code.Where(x => x is MichelinePrim p && p.Prim == PrimType.view);
                var script         = new Script
                {
                    Id              = Cache.AppState.NextScriptId(),
                    Level           = 1,
                    ContractId      = contract.Id,
                    ParameterSchema = micheParameter.ToBytes(),
                    StorageSchema   = micheStorage.ToBytes(),
                    CodeSchema      = micheCode.ToBytes(),
                    Views           = micheViews.Any()
                        ? micheViews.Select(x => x.ToBytes()).ToArray()
                        : null,
                    Current = true
                };

                var viewsBytes = script.Views?
                                 .OrderBy(x => x, new BytesComparer())
                                 .SelectMany(x => x)
                                 .ToArray()
                                 ?? Array.Empty <byte>();
                var typeSchema = script.ParameterSchema.Concat(script.StorageSchema).Concat(viewsBytes);
                var fullSchema = typeSchema.Concat(script.CodeSchema);
                contract.TypeHash = script.TypeHash = Script.GetHash(typeSchema);
                contract.CodeHash = script.CodeHash = Script.GetHash(fullSchema);

                if (script.Schema.IsFA1())
                {
                    if (script.Schema.IsFA12())
                    {
                        contract.Tags |= ContractTags.FA12;
                    }

                    contract.Tags |= ContractTags.FA1;
                    contract.Kind  = ContractKind.Asset;
                }
                if (script.Schema.IsFA2())
                {
                    contract.Tags |= ContractTags.FA2;
                    contract.Kind  = ContractKind.Asset;
                }

                Db.Scripts.Add(script);
                Cache.Schemas.Add(contract, script.Schema);
                #endregion

                #region storage
                var storageValue = Micheline.FromJson(storageStr);
                var storage      = new Storage
                {
                    Id         = Cache.AppState.NextStorageId(),
                    Level      = 1,
                    ContractId = contract.Id,
                    RawValue   = script.Schema.OptimizeStorage(storageValue, false).ToBytes(),
                    JsonValue  = script.Schema.HumanizeStorage(storageValue),
                    Current    = true
                };

                Db.Storages.Add(storage);
                Cache.Storages.Add(contract, storage);
                #endregion
            }
            #endregion

            Db.Accounts.AddRange(accounts);

            #region migration ops
            var block = Cache.Blocks.Current();

            block.Operations |= Operations.Migrations;
            if (accounts.Any(x => x.Type == AccountType.Contract))
            {
                block.Events |= BlockEvents.SmartContracts;
            }

            foreach (var account in accounts)
            {
                var migration = new MigrationOperation
                {
                    Id            = Cache.AppState.NextOperationId(),
                    Block         = block,
                    Level         = block.Level,
                    Timestamp     = block.Timestamp,
                    Account       = account,
                    Kind          = MigrationKind.Bootstrap,
                    BalanceChange = account.Balance,
                };

                if (account is Contract contract)
                {
                    var script = Db.ChangeTracker.Entries()
                                 .First(x => x.Entity is Script s && s.ContractId == contract.Id).Entity as Script;
                    var storage = await Cache.Storages.GetAsync(contract);

                    script.MigrationId  = migration.Id;
                    storage.MigrationId = migration.Id;

                    migration.Script  = script;
                    migration.Storage = storage;
                }

                Db.MigrationOps.Add(migration);
                account.MigrationsCount++;
            }

            var state = Cache.AppState.Get();
            state.MigrationOpsCount += accounts.Count;
            #endregion

            #region statistics
            var stats = await Cache.Statistics.GetAsync(1);

            stats.TotalBootstrapped = accounts.Sum(x => x.Balance);
            stats.TotalVested       = accounts.Where(x => x.Type == AccountType.Contract).Sum(x => x.Balance);
            #endregion

            return(accounts);
        }