public AccountWrapper CreateAccount(int id, RawPubKey pubkey, RequestRateLimits rateLimits)
        {
            if (pubkey == null)
            {
                throw new ArgumentNullException(nameof(pubkey));
            }

            if (accountIds.ContainsKey(pubkey))
            {
                throw new InvalidOperationException($"Account with public key {pubkey} already exists");
            }

            var acc = new AccountWrapper(new Account
            {
                Id       = id,
                Pubkey   = pubkey,
                Balances = new List <Balance>()
            },
                                         rateLimits
                                         );

            accountIds.Add(pubkey, id);
            accounts.Add(id, acc);

            return(acc);
        }
Пример #2
0
        private bool AddQuanta(RawPubKey pubKey, AuditorState currentState, AuditorState newAuditorState)
        {
            if (!currentState.HasMorePendingQuanta ||
                newAuditorState.HasMorePendingQuanta && newAuditorState.PendingQuanta.Count < 1)    //prevent spamming
            {
                logger.Trace($"Unable to add auditor's {((KeyPair)pubKey).AccountId} quanta.");
                currentState.HasMorePendingQuanta = false;
                return(false);
            }
            currentState.HasMorePendingQuanta = newAuditorState.HasMorePendingQuanta;
            var lastAddedApex = currentState.PendingQuanta.LastOrDefault()?.Message.MessageId ?? -1;
            var alphaPubkey   = (RawPubKey)Context.Settings.KeyPair.PublicKey;

            foreach (var envelope in newAuditorState.PendingQuanta)
            {
                var currentQuantum = (Quantum)envelope.Message;
                if (lastAddedApex != -1 && currentQuantum.Apex != lastAddedApex + 1)
                {
                    return(false);
                }
                lastAddedApex = currentQuantum.Apex;
                if (envelope.Signatures.All(s => !s.Signer.Equals(alphaPubkey)) || !envelope.AreSignaturesValid())
                {
                    return(false);
                }
                currentState.PendingQuanta.Add(envelope);
            }
            logger.Trace($"Auditor's {((KeyPair)pubKey).AccountId} quanta added.");
            return(true);
        }
Пример #3
0
 /// <summary>
 /// Sends the message to the account
 /// </summary>
 /// <param name="account">Target account</param>
 /// <param name="envelope">Message to send</param>
 public static void Notify(RawPubKey account, MessageEnvelope envelope)
 {
     Global.ExtensionsManager.BeforeNotify(account, envelope);
     if (ConnectionManager.TryGetConnection(account, out Centaurus.AlphaWebSocketConnection connection))
     {
         _ = connection.SendMessage(envelope);
     }
 }
Пример #4
0
        public void Add(AuditorResultMessage resultMessage, RawPubKey auditor)
        {
            if (!pendingAggregates.TryGetValue(resultMessage.Apex, out var aggregate))
            {
                return;
            }

            //add the signature to the aggregate
            aggregate.Add(resultMessage, auditor);
        }
 public void AuditorConnectionClosed(RawPubKey rawPubKey)
 {
     lock (this)
     {
         ConnectedAuditors.Remove(rawPubKey);
         if (!HasMajority && State == ApplicationState.Ready)
         {
             State = ApplicationState.Running;
         }
     }
 }
 public void RegisterAuditorState(RawPubKey rawPubKey, ConnectionState connectionState)
 {
     lock (this)
     {
         ConnectedAuditors[rawPubKey] = connectionState;
         if (HasMajority && State == ApplicationState.Running)
         {
             State = ApplicationState.Ready;
         }
     }
 }
Пример #7
0
 public void AuditorConnected(RawPubKey rawPubKey)
 {
     lock (this)
     {
         ConnectedAuditors.Add(rawPubKey);
         if (HasMajority && State == ApplicationState.Running)
         {
             State = ApplicationState.Ready;
         }
     }
 }
Пример #8
0
 /// <summary>
 /// Checks that envelope is signed with specified key
 /// !!!This method doesn't validate signature
 /// </summary>
 /// <param name="envelope">Target envelope</param>
 /// <param name="pubKey">Required signer public key</param>
 /// <returns>True if signed, otherwise false</returns>
 public static bool IsSignedBy(this MessageEnvelope envelope, RawPubKey pubKey)
 {
     if (envelope == null)
     {
         throw new ArgumentNullException(nameof(envelope));
     }
     if (pubKey == null)
     {
         throw new ArgumentNullException(nameof(pubKey));
     }
     return(envelope.Signatures.Any(s => s.Signer.Equals(pubKey)));
 }
Пример #9
0
 /// <summary>
 /// Sends the message to the account
 /// </summary>
 /// <param name="account">Target account</param>
 /// <param name="envelope">Message to send</param>
 public static void Notify(this AlphaContext context, RawPubKey account, MessageEnvelope envelope)
 {
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     context.ExtensionsManager.BeforeNotify(account, envelope);
     if (context.ConnectionManager.TryGetConnection(account, out AlphaWebSocketConnection connection))
     {
         Task.Factory.StartNew(async() => await connection.SendMessage(envelope)).Unwrap();
     }
 }
Пример #10
0
 public void RemoveState(RawPubKey pubKey)
 {
     semaphoreSlim.Wait();
     try
     {
         allAuditorStates.Remove(pubKey);
         validAuditorStates.Remove(pubKey);
     }
     finally
     {
         semaphoreSlim.Release();
     }
 }
Пример #11
0
        /// <summary>
        /// Retrieve account record by its public key.
        /// </summary>
        /// <param name="pubkey">Account public key</param>
        /// <returns>Account record, or null if not found</returns>
        public AccountWrapper GetAccount(RawPubKey pubkey)
        {
            if (pubkey == null)
            {
                throw new ArgumentNullException(nameof(pubkey));
            }
            var accId = accountIds.GetValueOrDefault(pubkey);

            if (accId == default)
            {
                return(null);
            }
            return(GetAccount(accId));
        }
Пример #12
0
        public void RemoveAccount(RawPubKey pubkey)
        {
            if (pubkey == null)
            {
                throw new ArgumentNullException(nameof(pubkey));
            }

            if (!accountIds.TryGetValue(pubkey, out var id))
            {
                throw new InvalidOperationException($"Account with public key {pubkey} doesn't exist");
            }

            if (!accounts.Remove(id))
            {
                throw new InvalidOperationException($"Account with id {id} doesn't exist");
            }

            if (!accountIds.Remove(pubkey))
            {
                throw new Exception($"Account with public key {pubkey} doesn't exist");
            }
        }
Пример #13
0
            public void Add(AuditorResultMessage result, RawPubKey auditor)
            {
                lock (syncRoot)
                {
                    if (IsProcessed || processedAuditors.Any(a => a.Equals(auditor)))
                    {
                        return;
                    }

                    processedAuditors.Add(auditor);

                    var signature = new Ed25519Signature {
                        Signature = result.Signature, Signer = auditor
                    };
                    if (signature.IsValid(resultMessageItem.Hash) &&
                        !(resultMessageItem.IsTxResultMessage && result.TxSignature == null))
                    {
                        resultMessageItem.ResultEnvelope.Signatures.Add(signature);
                        if (resultMessageItem.IsTxResultMessage)
                        {
                            var txSignature = new Ed25519Signature {
                                Signature = result.TxSignature, Signer = auditor
                            };
                            ((ITransactionResultMessage)resultMessageItem.ResultMessage).TxSignatures.Add(txSignature);
                        }
                    }
                    var majorityResult = CheckMajority();
                    if (majorityResult == MajorityResults.Unknown)
                    {
                        return;
                    }

                    OnResult(majorityResult);
                    resultManager.Remove(resultMessageItem.Apex);
                    IsProcessed = true;
                }
            }
Пример #14
0
 public CentaurusResponse(RawPubKey alphaPubKey, RawPubKey[] auditors, int requestTimeout)
 {
     AlphaPubkey = alphaPubKey;
     Auditors    = auditors;
     _           = StartRequestTimer(requestTimeout);
 }
Пример #15
0
        public static async Task AddAuditorState(RawPubKey pubKey, AuditorState auditorState)
        {
            await semaphoreSlim.WaitAsync();

            try
            {
                if (Global.AppState.State != ApplicationState.Rising)
                {
                    throw new InvalidOperationException("Auditor state messages can be only handled when Alpha is in rising state");
                }

                if (allAuditorStates.TryGetValue(pubKey, out var pendingAuditorState))
                {
                    if (!pendingAuditorState.HasMorePendingQuanta) //check if auditor send all quanta already
                    {
                        return;
                    }
                    allAuditorStates[pubKey].PendingQuanta.AddRange(auditorState.PendingQuanta);
                    allAuditorStates[pubKey].HasMorePendingQuanta = auditorState.HasMorePendingQuanta;
                }
                else
                {
                    allAuditorStates.Add(pubKey, auditorState);
                }
                var currentAuditorState = allAuditorStates[pubKey];

                if (currentAuditorState.HasMorePendingQuanta) //wait while auditor will send all quanta it has
                {
                    return;
                }

                if (IsStateValid(currentAuditorState))
                {
                    validAuditorStates.Add(pubKey, currentAuditorState);
                }

                int majority           = MajorityHelper.GetMajorityCount(),
                    totalAuditorsCount = MajorityHelper.GetTotalAuditorsCount();

                var completedStatesCount = allAuditorStates.Count(s => !s.Value.HasMorePendingQuanta);

                if (completedStatesCount < majority)
                {
                    return;
                }

                var possibleConsensusCount = (totalAuditorsCount - completedStatesCount) + validAuditorStates.Count;
                if (validAuditorStates.Count >= majority)
                {
                    await ApplyAuditorsData();
                }
                else if (possibleConsensusCount < majority)
                {
                    logger.Error("Majority of auditors are connected, but there is no consensus");
                    Global.AppState.State = ApplicationState.Failed;
                }
            }
            catch (Exception exc)
            {
                logger.Error(exc, "Error on adding auditors state");
                Global.AppState.State = ApplicationState.Failed;
            }
            finally
            {
                semaphoreSlim.Release();
            }
        }
 public static void AddAccountCreate(this EffectProcessorsContainer effectProcessors, AccountStorage accountStorage, int accountId, RawPubKey publicKey)
 {
     effectProcessors.Add(new AccountCreateEffectProcessor(
                              new AccountCreateEffect
     {
         Account = accountId,
         Pubkey  = publicKey,
         Apex    = effectProcessors.Apex
     },
                              accountStorage,
                              effectProcessors.Context.Constellation.RequestRateLimits
                              ));
 }
Пример #17
0
 public void BeforeNotify(RawPubKey pubKey, MessageEnvelope envelope)
 {
     OnBeforeNotify?.Invoke(pubKey, envelope);
 }
Пример #18
0
        public async Task AddAuditorState(RawPubKey pubKey, AuditorState auditorState)
        {
            await semaphoreSlim.WaitAsync();

            try
            {
                if (!applyDataTimer.Enabled) //start timer
                {
                    applyDataTimer.Start();
                }

                logger.Trace($"Auditor state from {((KeyPair)pubKey).AccountId} received by AlphaCatchup.");
                if (Context.AppState.State != ApplicationState.Rising)
                {
                    logger.Warn($"Auditor state messages can be only handled when Alpha is in rising state. State sent by {((KeyPair)pubKey).AccountId}");
                    return;
                }

                if (!allAuditorStates.TryGetValue(pubKey, out var pendingAuditorState))
                {
                    pendingAuditorState = new AuditorState
                    {
                        HasMorePendingQuanta = true,
                        PendingQuanta        = new List <MessageEnvelope>()
                    };
                    allAuditorStates.Add(pubKey, pendingAuditorState);
                    logger.Trace($"Auditor state from {((KeyPair)pubKey).AccountId} added.");
                }

                if (AddQuanta(pubKey, pendingAuditorState, auditorState)) //check if auditor sent all quanta already
                {
                    if (pendingAuditorState.HasMorePendingQuanta)         //wait while auditor will send all quanta it has
                    {
                        logger.Trace($"Auditor {((KeyPair)pubKey).AccountId} has more quanta. Timer reseted.");
                        applyDataTimer.Reset(); //if timer is running reset it. We need to try to wait all possible auditors data
                        return;
                    }
                    logger.Trace($"Auditor {((KeyPair)pubKey).AccountId} state is validated.");
                    validAuditorStates.Add(pubKey, pendingAuditorState);
                }

                int majority           = Context.GetMajorityCount(),
                    totalAuditorsCount = Context.GetTotalAuditorsCount();

                var completedStatesCount = allAuditorStates.Count(s => !s.Value.HasMorePendingQuanta);

                if (completedStatesCount == totalAuditorsCount)
                {
                    await TryApplyAuditorsData();
                }
            }
            catch (Exception exc)
            {
                logger.Error(exc, "Error on adding auditors state");
                Context.AppState.State = ApplicationState.Failed;
            }
            finally
            {
                semaphoreSlim.Release();
            }
        }
 public static void AddAccountCreate(this EffectProcessorsContainer effectProcessors, AccountStorage accountStorage, int accountId, RawPubKey publicKey)
 {
     effectProcessors.Add(new AccountCreateEffectProcessor(
                              new AccountCreateEffect
     {
         AccountId = accountId,
         Pubkey    = publicKey,
         Apex      = effectProcessors.Apex
     },
                              accountStorage
                              ));
 }
Пример #20
0
 public CentaurusQuantumResponse(RawPubKey alphaPubKey, RawPubKey[] auditors, int requestTimeout)
     : base(alphaPubKey, auditors, requestTimeout)
 {
 }
Пример #21
0
 /// <summary>
 /// Gets the connection by the account public key
 /// </summary>
 /// <param name="pubKey">Account public key</param>
 /// <param name="connection">Current account connection</param>
 /// <returns>True if connection is found, otherwise false</returns>
 public static bool TryGetConnection(RawPubKey pubKey, out AlphaWebSocketConnection connection)
 {
     return(connections.TryGetValue(pubKey, out connection));
 }