public bool IsSignedBy(string user) { var pubkey = PubKey.FromBase58(user); /* Console.WriteLine(pubkey.Address); * Console.WriteLine("data length: {0}",data.Length); * Console.WriteLine("signature length: {0}", signed.Length); */ return(pubkey.Verify(Hex.Parse("03" + data), Hex.Parse(signature))); }
public bool TryAuthenticate(AuthHeaders headers, out string error) { error = null; if (string.IsNullOrEmpty(headers?.User)) { error = $"The X-TZKT-USER header is required"; return(false); } if (headers.Nonce == null) { error = $"The X-TZKT-NONCE header is required"; return(false); } if (string.IsNullOrEmpty(headers.Signature)) { error = $"The X-TZKT-SIGNATURE header is required"; return(false); } if (!Config.Credentials.TryGetValue(headers.User, out var pubKey)) { error = $"User {headers.User} doesn't exist"; return(false); } var nonce = (long)headers.Nonce; var nonceTime = DateTime.UnixEpoch.AddMilliseconds(nonce); if (nonceTime < DateTime.UtcNow.AddSeconds(-Config.NonceLifetime)) { error = $"Nonce too old. Server time: {DateTime.UtcNow}, nonce: {nonceTime}"; return(false); } if (nonce <= Nonces[headers.User]) { error = $"Nonce {nonce} has already used"; return(false); } var key = PubKey.FromBase58(pubKey); if (!key.Verify($"{headers.Nonce}", headers.Signature)) { error = $"Invalid signature"; return(false); } Nonces[headers.User] = nonce; return(true); }
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); }