public ChainRegistrationEvent(HeleusClientResponse response, ChainInfo chainInfo) { ChainOperation = response.Transaction as ChainInfoOperation; Response = response; ChainInfo = chainInfo; }
TransactionResultTypes ConsumeTransaction(CoreTransaction transaction, bool addExtraTime) { if (transaction.IsExpired(addExtraTime)) { return(TransactionResultTypes.Expired); } var r = _coreChain.BlockStorage.HistoryContainsTransactionOrRegistration(transaction); if (r != TransactionResultTypes.Ok) { return(r); } var coreType = transaction.TransactionType; if (coreType != CoreTransactionTypes.AccountRegistration) { var account = GetCoreAccount(transaction.AccountId); if (account == null) { return(TransactionResultTypes.InvalidCoreAccount); } var key = account.AccountKey; if (coreType == CoreTransactionTypes.ChainUpdate) { var update = transaction as ChainUpdateCoreTransaction; var chain = GetChainInfo(update.ChainId); var keyIndex = update.SignKeyIndex; if (keyIndex != Protocol.CoreAccountSignKeyIndex) { var result = CheckChainKey(update.ChainId, keyIndex, true, ref key); if (result != TransactionResultTypes.Ok) { return(result); } } else if (transaction.AccountId != chain.AccountId) { return(TransactionResultTypes.InvalidCoreAccount); } } else if (coreType == CoreTransactionTypes.ServiceBlock) { var serviceBlockTransaction = transaction as ServiceBlockCoreTransaction; var block = serviceBlockTransaction.ServiceBlock; key = _coreChain.GetValidPublicChainKeyWithFlags(block.ChainId, block.ChainIndex, block.Issuer, PublicChainKeyFlags.ServiceChainVoteKey, transaction.Timestamp)?.PublicKey; } if (!transaction.IsSignatureValid(key)) { return(TransactionResultTypes.InvalidSignature); } } else { var register = transaction as AccountRegistrationCoreTransaction; if (!transaction.IsSignatureValid(register.PublicKey)) { return(TransactionResultTypes.InvalidSignature); } } if (coreType == CoreTransactionTypes.AccountRegistration) { var registration = transaction as AccountRegistrationCoreTransaction; var account = new CoreAccount(NextAccountId, registration.PublicKey); _accounts[account.AccountId] = account; NextAccountId++; _blockInfo.AddNewAccount(registration, account); return(TransactionResultTypes.Ok); } if (coreType == CoreTransactionTypes.ChainRegistration || coreType == CoreTransactionTypes.ChainUpdate) { var update = transaction as ChainUpdateCoreTransaction; var registration = transaction as ChainRegistrationCoreTransaction; var isUpdate = update != null; var account = GetCoreAccount(transaction.AccountId); if (account == null) { return(TransactionResultTypes.InvalidCoreAccount); } ChainInfo chain = null; if (isUpdate) { chain = GetChainInfo(update.ChainId); if (chain == null) { return(TransactionResultTypes.ChainNotFound); } } if (!registration.ChainWebsite.IsValdiUrl()) { return(TransactionResultTypes.InvalidChainWebsite); } if (registration.ChainName != null && registration.ChainName.Length > ChainRegistrationCoreTransaction.MaxNameLength) { return(TransactionResultTypes.InvalidChainName); } foreach (var endPoint in registration.PublicEndpoints) { if (!endPoint.IsValdiUrl(false)) { return(TransactionResultTypes.InvalidChainEndpoint); } } var indices = new HashSet <short>(); foreach (var chainKey in registration.ChainKeys) { if (indices.Contains(chainKey.KeyIndex)) { return(TransactionResultTypes.InvaidChainKey); } indices.Add(chainKey.KeyIndex); } foreach (var purchase in registration.Purchases) { if (purchase.PurchaseType == PurchaseTypes.None) { return(TransactionResultTypes.InvalidChainPurchase); } foreach (var p in registration.Purchases) { if (purchase == p) { continue; } if (p.PurchaseItemId == purchase.PurchaseItemId && p.PurchaseGroupId == purchase.PurchaseGroupId) { return(TransactionResultTypes.InvalidChainPurchase); } if (p.PurchaseGroupId == purchase.PurchaseGroupId && p.PurchaseType != purchase.PurchaseType) { return(TransactionResultTypes.InvalidChainPurchase); } } } if (!isUpdate) { chain = new ChainInfo(NextChainId, registration.AccountId, registration.ChainName, registration.ChainWebsite); var operation = new ChainInfoOperation(chain.ChainId, chain.AccountId, chain.Name, chain.Website, registration.Timestamp, registration.ChainKeys, registration.PublicEndpoints, registration.Purchases); _chains[chain.ChainId] = chain; NextChainId++; _blockInfo.AddChainUpdate(registration, operation); } else { var result = chain.IsUpdateValid(update); if (result != TransactionResultTypes.Ok) { return(result); } var operation = new ChainInfoOperation(chain.ChainId, update.AccountId, update.ChainName, update.ChainWebsite, registration.Timestamp, update.ChainKeys, update.PublicEndpoints, update.Purchases, update.RevokeChainKeys, update.RemovePublicEndPoints, update.RemovePurchaseItems); _blockInfo.AddChainUpdate(update, operation); } return(TransactionResultTypes.Ok); } if (coreType == CoreTransactionTypes.Transfer) { var transfer = transaction as TransferCoreTransaction; if (!AccountUpdateOperation.IsReasonValid(transfer.Reason)) { return(TransactionResultTypes.InvalidTransferReason); } if (transfer.AccountId == transfer.ReceiverAccountId) { return(TransactionResultTypes.InvalidReceiverAccount); } var sender = GetCoreAccount(transfer.AccountId); var receiver = GetCoreAccount(transfer.ReceiverAccountId); if (receiver == null) { return(TransactionResultTypes.InvalidReceiverAccount); } if (sender != null) { var amount = transfer.Amount; if (sender.CanTransfer(amount)) { sender.RemoveFromTranfser(amount); receiver.AddFromTransfer(amount); _blockInfo.AddTransfer(transfer); return(TransactionResultTypes.Ok); } return(TransactionResultTypes.InsuficientBalance); } return(TransactionResultTypes.InvalidTransaction); } if (coreType == CoreTransactionTypes.ServiceBlock) { var serviceBlockTransaction = (transaction as ServiceBlockCoreTransaction); var block = serviceBlockTransaction.ServiceBlock; var chainInfo = GetChainInfo(block.ChainId); if (chainInfo == null) { return(TransactionResultTypes.ChainNotFound); } if (block.TransactionCount == 0) { return(TransactionResultTypes.InvalidTransaction); } var state = chainInfo.LastState; if ((state.BlockId + 1) != block.BlockId) { return(TransactionResultTypes.InvalidBlock); } foreach (var serviceTransaction in block.Transactions) { var serviceType = serviceTransaction.TransactionType; var accountId = serviceTransaction.AccountId; var account = GetCoreAccount(accountId); if (account == null) { return(TransactionResultTypes.InvalidCoreAccount); } if (!serviceTransaction.IsSignatureValid(account.AccountKey)) { return(TransactionResultTypes.InvalidSignature); } if (serviceType == ServiceTransactionTypes.Join) { var joinTransaction = serviceTransaction as JoinServiceTransaction; var key = joinTransaction.AccountKey; if (key == null || (key != null && key.IsKeySignatureValid(account.AccountKey))) { continue; } return(TransactionResultTypes.InvalidSignature); } if (serviceType == ServiceTransactionTypes.Purchase) { var purchaseTransaction = serviceTransaction as PurchaseServiceTransaction; var buyer = GetCoreAccount(purchaseTransaction.AccountId); var receiver = GetCoreAccount(purchaseTransaction.ReceiverAccountId); if (buyer != null && receiver != null && chainInfo.IsPurchaseValid(purchaseTransaction.PurchaseGroupId, purchaseTransaction.PurchaseItemId, purchaseTransaction.Price)) { var chainAccount = GetCoreAccount(chainInfo.AccountId); if (chainAccount != null && buyer.CanPurchase(purchaseTransaction.Price)) { //buyer.Purchase(purchaseTransaction.Price, chainAccount); continue; } return(TransactionResultTypes.CannotPurchase); } return(TransactionResultTypes.InvalidCoreAccount); } if (serviceType == ServiceTransactionTypes.RequestRevenue) { var totalRevenue = chainInfo.GetTotalAccountRevenue(transaction.Timestamp); var totalPayout = chainInfo.TotalAccountPayout; var availablePayout = totalRevenue - totalPayout; var revenueTransaction = serviceTransaction as RequestRevenueServiceTransaction; if (availablePayout >= revenueTransaction.PayoutAmount) { continue; } } return(TransactionResultTypes.InvalidTransaction); } if (!_coreChain.IsBlockProposalSignatureValid(block, serviceBlockTransaction.ProposalSignatures)) { return(TransactionResultTypes.InvalidBlockSignature); } _blockInfo.AddServiceBlock(serviceBlockTransaction); return(TransactionResultTypes.Ok); } return(TransactionResultTypes.InvalidTransaction); }
public ChainUpdateInfo(ChainRegistrationCoreTransaction transaction, ChainInfoOperation operation) { Transaction = transaction; Operation = operation; }
public void AddChainUpdate(ChainRegistrationCoreTransaction transaction, ChainInfoOperation operation) { Chains.Add(new ChainUpdateInfo(transaction, operation)); }
public static GenesisBlockResult Generate(Base.Storage storage) { (var networkKeyStore, var networkKey, _) = LoadCoreAccountKey(storage, "Network Account", "Heleus Core"); if (networkKeyStore == null) { networkKey = Key.Generate(KeyTypes.Ed25519); var networkPassword = Hex.ToString(Rand.NextSeed(32)); networkKeyStore = new CoreAccountKeyStore("Heleus Core Network Account", CoreAccount.NetworkAccountId, networkKey, networkPassword); SaveCoreAccountKey(storage, networkKeyStore, "Network Account", networkPassword, "Heleus Core"); } Console.WriteLine($"Heleus Core Network Account Key: {networkKey.PublicKey.HexString}."); var networkKeys = new List <NetworkKey>(); var networkChainKeys = new List <PublicChainKey>(); for (var i = 0; i < 3; i++) { var keyFlags = GetCoreKeyFlags(i); var keyName = $"Network {GetKeyName(keyFlags, true)}"; (var store, var key, var storePassword) = LoadKeyStore <ChainKeyStore>(storage, null, keyName, "Heleus Core"); if (store == null) { key = Key.Generate(KeyTypes.Ed25519); storePassword = Hex.ToString(Rand.NextSeed(32)); var publicChainKey = new PublicChainKey(keyFlags, CoreChain.CoreChainId, 0, 0, (short)i, key); store = new ChainKeyStore($"Heleus Core {keyName}", publicChainKey, key, storePassword); SaveKeyStore(storage, store, storePassword, null, keyName, "Heleus Core"); } Console.WriteLine($"Heleus Core {keyName}: {key.PublicKey.HexString}."); networkKeys.Add(new NetworkKey { Key = key, Password = storePassword, PublicKey = store.PublicChainKey, Store = store }); networkChainKeys.Add(store.PublicChainKey); } var timestamp = Time.Timestamp; timestamp = Protocol.GenesisTime; var coreOperations = new List <CoreOperation>(); var endPoints = new List <string>(); Console.WriteLine("Type the core chain name (default: Heleus Core)"); var name = Program.IsDebugging ? "Heleus Core" : Console.ReadLine(); if (string.IsNullOrWhiteSpace(name)) { name = "Heleus Core"; } Console.WriteLine($"Chain name: {name}"); Console.WriteLine("Type the core chain website (default: https://heleuscore.com)"); var website = Program.IsDebugging ? "https://heleuscore.com" : Console.ReadLine(); if (string.IsNullOrWhiteSpace(website)) { website = "https://heleuscore.com"; } Console.WriteLine($"Chain Website: {website}"); Console.WriteLine("Type the core chain endpoints. (none for none, default: https://heleusnode.heleuscore.com)"); while (true) { if (Program.IsDebugging) { var ips = GetLocalIPV4Addresss(); foreach (var ip in ips) { endPoints.Add($"http://{ip}:54321/"); } break; } var ep = Console.ReadLine(); if (string.IsNullOrWhiteSpace(ep)) { if (endPoints.Count == 0) { endPoints.Add("https://heleusnode.heleuscore.com"); } break; } if (ep.IsValdiUrl(false)) { Console.WriteLine($"Added endpoint {ep}"); endPoints.Add(ep); } if (ep == "none") { break; } } Console.WriteLine($"Chain Endpoints: {string.Join(", ", endPoints)}"); var useGenesisInfo = false; var useCoreChainEndpoint = false; if (storage.FileExists("genesisservices.txt")) { Console.WriteLine("Process genesisservices.txt [yes/no] (default: yes)"); var p = Program.IsDebugging ? "yes" : Console.ReadLine(); if (string.IsNullOrWhiteSpace(p) || p.ToLower() == "yes") { Console.WriteLine("Processing genesisservices.txt"); useGenesisInfo = true; if (endPoints.Count > 0) { Console.WriteLine("Use first core chain endpoint, not endpoint from genesisservices.txt [yes/no] (default: no)"); var p2 = Program.IsDebugging ? "yes" : Console.ReadLine()?.ToLower(); if (p2 == "yes") { useCoreChainEndpoint = true; Console.WriteLine($"Using endpoint {endPoints[0]} for all services from genesisservices.txt"); } } } } coreOperations.Add((ChainInfoOperation) new ChainInfoOperation(CoreChain.CoreChainId, CoreAccount.NetworkAccountId, name, website, timestamp, networkChainKeys, endPoints, new List <PurchaseInfo>()).UpdateOperationId(Operation.FirstTransactionId)); coreOperations.Add((AccountOperation) new AccountOperation(CoreAccount.NetworkAccountId, networkKey.PublicKey, timestamp).UpdateOperationId(coreOperations.Count + 1)); // network account coreOperations.Add(((AccountUpdateOperation) new AccountUpdateOperation().UpdateOperationId(Operation.FirstTransactionId + 2)).AddAccount(CoreAccount.NetworkAccountId, coreOperations.Count + 1, long.MaxValue / 2).AddTransfer(CoreAccount.NetworkAccountId, CoreAccount.NetworkAccountId, long.MaxValue / 2, null, timestamp)); var blockStateOperation = new BlockStateOperation(); var nextChainId = CoreChain.CoreChainId + 1; var nextTransactionId = coreOperations.Count + 1; var nextAccountId = CoreAccount.NetworkAccountId + 1; var accounts = new List <AccountOperation>(); var serviceTransactionsList = new Dictionary <int, List <ServiceTransaction> >(); if (useGenesisInfo) { try { var json = storage.ReadFileText("genesisservices.txt"); if (json != null) { var services = Newtonsoft.Json.JsonConvert.DeserializeObject <List <GenesisService> >(json); if (services != null) { foreach (var service in services) { if (!service.Valid) { continue; } var serviceKeys = new List <PublicChainKey>(); var ep = useCoreChainEndpoint ? endPoints[0] : service.Endpoint; var accountId = service.AccountId; if (accountId != CoreAccount.NetworkAccountId) { var found = accounts.Find((a) => a.AccountId == accountId) != null; if (!found) { (var store, var key, var accountPassword) = LoadCoreAccountKey(storage, "Core Account " + accountId, "Core Accounts"); if (store == null) { key = Key.Generate(KeyTypes.Ed25519); accountPassword = Hex.ToString(Rand.NextSeed(32)); store = new CoreAccountKeyStore(service.AccountName, accountId, key, accountPassword); SaveCoreAccountKey(storage, store, "Core Account " + accountId, accountPassword, "Core Accounts"); } if (accountId == nextAccountId) { var ao = new AccountOperation(accountId, key.PublicKey, timestamp); ao.UpdateOperationId(nextTransactionId); coreOperations.Add(ao); accounts.Add(ao); nextTransactionId++; nextAccountId++; } else { Console.WriteLine($"Invalid account id for {service.Title}, should be {nextAccountId}, but is {accountId}."); continue; } } } Console.WriteLine($"Adding Service {service.Title} with endpoint {ep}."); var count = 2 + service.DataChainCount; for (var i = 0; i < count; i++) { var keyFlags = GetServiceKeyFlags(i); var keyName = $"{service.Name} {GetKeyName(keyFlags, false)}"; var dataChain = i >= 2; if (dataChain) { keyName += $" (ChainIndex {i - 2})"; } (var store, var key, var servicePassword) = LoadKeyStore <ChainKeyStore>(storage, null, keyName, service.Name); if (store == null) { key = Key.Generate(KeyTypes.Ed25519); servicePassword = Hex.ToString(Rand.NextSeed(32)); var signedKey = new PublicChainKey(keyFlags, nextChainId, dataChain ? (uint)i - 2 : 0, 0, (short)i, key); store = new ChainKeyStore($"{service.Name} {keyName}", signedKey, key, servicePassword); SaveKeyStore(storage, store, servicePassword, null, keyName, service.Name); } Console.WriteLine($"{service.Name} {keyName}: {key.PublicKey.HexString}."); serviceKeys.Add(store.PublicChainKey); } var pc = new ChainInfoOperation(nextChainId, accountId, service.Title, service.Website, timestamp, serviceKeys, new List <string> { ep }, new List <PurchaseInfo>()); pc.UpdateOperationId(nextTransactionId); coreOperations.Add(pc); nextTransactionId++; if (service.Revenue > 0) { var rev = new ChainRevenueInfoOperation(nextChainId, service.Revenue, service.RevenueAccountFactor, timestamp); rev.UpdateOperationId(nextTransactionId); coreOperations.Add(rev); nextTransactionId++; } if (service.Accounts > 0) { var serviceTransactions = new List <ServiceTransaction>(); for (var i = 0; i < service.Accounts; i++) { (var accountStore, var accountKey, var accountPassword) = LoadCoreAccountKey(storage, "Core Account " + nextAccountId, "Core Accounts"); if (accountStore == null) { accountKey = Key.Generate(KeyTypes.Ed25519); accountPassword = Hex.ToString(Rand.NextSeed(32)); accountStore = new CoreAccountKeyStore($"Core Account {nextAccountId}", nextAccountId, accountKey, accountPassword); SaveCoreAccountKey(storage, accountStore, "Core Account " + nextAccountId, accountPassword, "Core Accounts"); } (var serviceAccountStore, var serviceAccountKey, var serviceAccountPassword) = LoadKeyStore <ServiceAccountKeyStore>(storage, null, $"{service.Name} Service Account {nextAccountId}", $"{service.Name}/Service Accounts"); if (serviceAccountStore == null) { serviceAccountKey = Key.Generate(KeyTypes.Ed25519); serviceAccountPassword = Hex.ToString(Rand.NextSeed(32)); var signedPublicKey = PublicServiceAccountKey.GenerateSignedPublicKey(nextAccountId, nextChainId, 0, 0, serviceAccountKey.PublicKey, accountKey); serviceAccountStore = new ServiceAccountKeyStore($"{service.Name} Service Account {nextAccountId}", signedPublicKey, serviceAccountKey, serviceAccountPassword); SaveKeyStore(storage, serviceAccountStore, serviceAccountPassword, null, $"{service.Name} Service Account {nextAccountId}", $"{service.Name}/Service Accounts"); } var join = new JoinServiceTransaction(serviceAccountStore.SignedPublicKey) { SignKey = accountKey }; join.ToArray(); serviceTransactions.Add(join); var ao = new AccountOperation(nextAccountId, accountKey.PublicKey, timestamp); ao.UpdateOperationId(nextTransactionId); coreOperations.Add(ao); accounts.Add(ao); nextTransactionId++; nextAccountId++; } blockStateOperation.AddBlockState(nextChainId, Protocol.GenesisBlockId, 0, 0, serviceTransactions.Count); serviceTransactionsList[nextChainId] = serviceTransactions; } nextChainId++; } } } } catch (Exception ex) { Log.HandleException(ex, LogLevels.Error); } } coreOperations.Add(blockStateOperation); blockStateOperation.UpdateOperationId(nextTransactionId); blockStateOperation.AddBlockState(Protocol.CoreChainId, Protocol.GenesisBlockId, Protocol.GenesisBlockNetworkKeyIssuer, 0, nextTransactionId); var block = new CoreBlock(Protocol.GenesisBlockId, Protocol.GenesisBlockNetworkKeyIssuer, 0, timestamp, nextAccountId, nextChainId, Hash.Empty(Protocol.TransactionHashType), Hash.Empty(ValidationOperation.ValidationHashType), coreOperations, new List <CoreTransaction>()); var signatures = new BlockSignatures(block); signatures.AddSignature(block.Issuer, block, networkKey); return(new GenesisBlockResult(block, signatures, networkKey.PublicKey, networkKeys[1].Store, networkKeys[1].Password, serviceTransactionsList)); }