コード例 #1
0
        public void UpdateAccountProperties(Account account, string name, uint externalKeyCount, uint internalKeyCount, uint importedKeyCount)
        {
            AccountProperties props;

            if (!_accounts.TryGetValue(account, out props))
            {
                props = new AccountProperties();
                _accounts[account] = props;
            }

            props.AccountName      = name;
            props.ExternalKeyCount = externalKeyCount;
            props.InternalKeyCount = internalKeyCount;
            props.ImportedKeyCount = importedKeyCount;

            var eventArgs = new ChangesProcessedEventArgs();

            eventArgs.ModifiedAccountProperties[account] = props;
            OnChangesProcessed(eventArgs);
        }
コード例 #2
0
        public void UpdateAccountProperties(Account account, string name, uint externalKeyCount, uint internalKeyCount, uint importedKeyCount)
        {
            AccountProperties props;

            if (account.AccountNumber == ImportedAccountNumber)
            {
                props = _importedAccount;
            }
            else
            {
                var accountNumber = checked ((int)account.AccountNumber);
                if (accountNumber < _bip0032Accounts.Count)
                {
                    props = _bip0032Accounts[accountNumber];
                }
                else if (accountNumber == _bip0032Accounts.Count)
                {
                    props = new AccountProperties();
                    _bip0032Accounts.Add(props);
                }
                else
                {
                    throw new Exception($"Account {accountNumber} is not the next BIP0032 account.");
                }
            }

            props.AccountName      = name;
            props.ExternalKeyCount = externalKeyCount;
            props.InternalKeyCount = internalKeyCount;
            props.ImportedKeyCount = importedKeyCount;

            var eventArgs = new ChangesProcessedEventArgs();

            eventArgs.ModifiedAccountProperties[account] = props;
            OnChangesProcessed(eventArgs);
        }
コード例 #3
0
ファイル: Wallet.cs プロジェクト: jrick/Paymetheus
        public void UpdateAccountProperties(Account account, string name, uint externalKeyCount, uint internalKeyCount, uint importedKeyCount)
        {
            AccountProperties props;
            if (account.AccountNumber == ImportedAccountNumber)
            {
                props = _importedAccount;
            }
            else
            {
                var accountNumber = checked((int)account.AccountNumber);
                if (accountNumber < _bip0032Accounts.Count)
                {
                    props = _bip0032Accounts[accountNumber];
                }
                else if (accountNumber == _bip0032Accounts.Count)
                {
                    props = new AccountProperties();
                    _bip0032Accounts.Add(props);
                }
                else
                {
                    throw new Exception($"Account {accountNumber} is not the next BIP0032 account.");
                }
            }

            props.AccountName = name;
            props.ExternalKeyCount = externalKeyCount;
            props.InternalKeyCount = internalKeyCount;
            props.ImportedKeyCount = importedKeyCount;

            var eventArgs = new ChangesProcessedEventArgs();
            eventArgs.ModifiedAccountProperties[account] = props;
            OnChangesProcessed(eventArgs);
        }
コード例 #4
0
ファイル: Wallet.cs プロジェクト: jrick/Paymetheus
        public void ApplyTransactionChanges(WalletChanges changes)
        {
            if (changes == null)
                throw new ArgumentNullException(nameof(changes));

            // A reorganize cannot be handled if the number of removed blocks exceeds the
            // minimum number saved in memory.
            if (changes.DetachedBlocks.Count >= NumRecentBlocks(ActiveChain))
                throw new BlockChainConsistencyException("Reorganize too deep");

            var newChainTip = changes.AttachedBlocks.LastOrDefault();
            if (ChainTip.Height >= newChainTip?.Height)
            {
                var msg = $"New chain tip {newChainTip.Hash} (height {newChainTip.Height}) neither extends nor replaces " +
                    $"the current chain (currently synced to hash {ChainTip.Hash}, height {ChainTip.Height})";
                throw new BlockChainConsistencyException(msg);
            }

            if (changes.NewUnminedTransactions.Any(tx => !changes.AllUnminedHashes.Contains(tx.Hash)))
                throw new BlockChainConsistencyException("New unmined transactions contains tx with hash not found in all unmined transaction hash set");

            var eventArgs = new ChangesProcessedEventArgs();

            var reorgedBlocks = RecentTransactions.MinedTransactions
                .ReverseList()
                .TakeWhile(b => changes.DetachedBlocks.Contains(b.Hash))
                .ToList();
            var numReorgedBlocks = reorgedBlocks.Count;
            foreach (var reorgedTx in reorgedBlocks.SelectMany(b => b.Transactions))
            {
                if (BlockChain.IsCoinbase(reorgedTx.Transaction) || !changes.AllUnminedHashes.Contains(reorgedTx.Hash))
                {
                    RemoveTransactionFromTotals(reorgedTx, eventArgs.ModifiedAccountProperties);
                }
                else
                {
                    RecentTransactions.UnminedTransactions[reorgedTx.Hash] = reorgedTx;
                    eventArgs.MovedTransactions.Add(reorgedTx.Hash, BlockIdentity.Unmined);
                }
            }
            var numRemoved = RecentTransactions.MinedTransactions.RemoveAll(block => changes.DetachedBlocks.Contains(block.Hash));
            if (numRemoved != numReorgedBlocks)
            {
                throw new BlockChainConsistencyException("Number of blocks removed exceeds those for which transactions were removed");
            }

            foreach (var block in changes.AttachedBlocks.Where(b => b.Transactions.Count > 0))
            {
                RecentTransactions.MinedTransactions.Add(block);

                foreach (var tx in block.Transactions)
                {
                    if (RecentTransactions.UnminedTransactions.ContainsKey(tx.Hash))
                    {
                        RecentTransactions.UnminedTransactions.Remove(tx.Hash);
                        eventArgs.MovedTransactions[tx.Hash] = block.Identity;
                    }
                    else if (!eventArgs.MovedTransactions.ContainsKey(tx.Hash))
                    {
                        AddTransactionToTotals(tx, eventArgs.ModifiedAccountProperties);
                        eventArgs.AddedTransactions.Add(Tuple.Create(tx, block.Identity));
                    }
                }
            }

            // TODO: What about new transactions which were not added in a newly processed
            // block (e.g. importing an address and rescanning for outputs)?

            foreach (var tx in changes.NewUnminedTransactions.Where(tx => !RecentTransactions.UnminedTransactions.ContainsKey(tx.Hash)))
            {
                RecentTransactions.UnminedTransactions[tx.Hash] = tx;
                AddTransactionToTotals(tx, eventArgs.ModifiedAccountProperties);

                // TODO: When reorgs are handled, this will need to check whether the transaction
                // being added to the unmined collection was previously in a block.
                eventArgs.AddedTransactions.Add(Tuple.Create(tx, BlockIdentity.Unmined));
            }

            var removedUnmined = RecentTransactions.UnminedTransactions
                .Where(kvp => !changes.AllUnminedHashes.Contains(kvp.Key))
                .ToList(); // Collect to list so UnminedTransactions can be modified below.
            foreach (var unmined in removedUnmined)
            {
                // Transactions that were mined rather than being removed from the unmined
                // set due to a conflict have already been removed.
                RecentTransactions.UnminedTransactions.Remove(unmined.Key);
                RemoveTransactionFromTotals(unmined.Value, eventArgs.ModifiedAccountProperties);
                eventArgs.RemovedTransactions.Add(unmined.Value);
            }

            if (newChainTip != null)
            {
                ChainTip = newChainTip.Identity;
                eventArgs.NewChainTip = newChainTip.Identity;
            }

            OnChangesProcessed(eventArgs);
        }
コード例 #5
0
ファイル: Wallet.cs プロジェクト: jrick/Paymetheus
 private void OnChangesProcessed(ChangesProcessedEventArgs e)
 {
     ChangesProcessed?.Invoke(this, e);
 }
コード例 #6
0
ファイル: Wallet.cs プロジェクト: tuxcanfly/Paymetheus
        public void UpdateAccountProperties(Account account, string name, uint externalKeyCount, uint internalKeyCount, uint importedKeyCount)
        {
            AccountState stats;
            if (!_accounts.TryGetValue(account, out stats))
            {
                stats = new AccountState();
                _accounts[account] = stats;
            }

            stats.AccountName = name;
            stats.ExternalKeyCount = externalKeyCount;
            stats.InternalKeyCount = internalKeyCount;
            stats.ImportedKeyCount = importedKeyCount;

            var eventArgs = new ChangesProcessedEventArgs();
            eventArgs.ModifiedAccountStates[account] = stats;
            OnChangesProcessed(eventArgs);
        }
コード例 #7
0
        public void ApplyTransactionChanges(WalletChanges changes)
        {
            if (changes == null)
            {
                throw new ArgumentNullException(nameof(changes));
            }

            // A reorganize cannot be handled if the number of removed blocks exceeds the
            // minimum number saved in memory.
            if (changes.DetachedBlocks.Count >= NumRecentBlocks)
            {
                throw new BlockChainConsistencyException("Reorganize too deep");
            }

            var newChainTip = changes.AttachedBlocks.LastOrDefault();

            if (ChainTip.Height >= newChainTip?.Height)
            {
                var msg = $"New chain tip {newChainTip.Hash} (height {newChainTip.Height}) neither extends nor replaces " +
                          $"the current chain (currently synced to hash {ChainTip.Hash}, height {ChainTip.Height})";
                throw new BlockChainConsistencyException(msg);
            }

            if (changes.NewUnminedTransactions.Any(tx => !changes.AllUnminedHashes.Contains(tx.Hash)))
            {
                throw new BlockChainConsistencyException("New unmined transactions contains tx with hash not found in all unmined transaction hash set");
            }

            var eventArgs = new ChangesProcessedEventArgs();

            var reorgedBlocks = RecentTransactions.MinedTransactions
                                .ReverseList()
                                .TakeWhile(b => changes.DetachedBlocks.Contains(b.Hash))
                                .ToList();
            var numReorgedBlocks = reorgedBlocks.Count;

            foreach (var reorgedTx in reorgedBlocks.SelectMany(b => b.Transactions))
            {
                if (BlockChain.IsCoinbase(reorgedTx.Transaction) || !changes.AllUnminedHashes.Contains(reorgedTx.Hash))
                {
                    RemoveTransactionFromTotals(reorgedTx, eventArgs.ModifiedAccountProperties);
                }
                else
                {
                    RecentTransactions.UnminedTransactions[reorgedTx.Hash] = reorgedTx;
                    eventArgs.MovedTransactions.Add(reorgedTx.Hash, BlockIdentity.Unmined);
                }
            }
            var numRemoved = RecentTransactions.MinedTransactions.RemoveAll(block => changes.DetachedBlocks.Contains(block.Hash));

            if (numRemoved != numReorgedBlocks)
            {
                throw new BlockChainConsistencyException("Number of blocks removed exceeds those for which transactions were removed");
            }

            foreach (var block in changes.AttachedBlocks.Where(b => b.Transactions.Count > 0))
            {
                RecentTransactions.MinedTransactions.Add(block);

                foreach (var tx in block.Transactions)
                {
                    if (RecentTransactions.UnminedTransactions.ContainsKey(tx.Hash))
                    {
                        RecentTransactions.UnminedTransactions.Remove(tx.Hash);
                        eventArgs.MovedTransactions[tx.Hash] = block.Identity;
                    }
                    else if (!eventArgs.MovedTransactions.ContainsKey(tx.Hash))
                    {
                        AddTransactionToTotals(tx, eventArgs.ModifiedAccountProperties);
                        eventArgs.AddedTransactions.Add(Tuple.Create(tx, block.Identity));
                    }
                }
            }

            // TODO: What about new transactions which were not added in a newly processed
            // block (e.g. importing an address and rescanning for outputs)?

            foreach (var tx in changes.NewUnminedTransactions.Where(tx => !RecentTransactions.UnminedTransactions.ContainsKey(tx.Hash)))
            {
                RecentTransactions.UnminedTransactions[tx.Hash] = tx;
                AddTransactionToTotals(tx, eventArgs.ModifiedAccountProperties);

                // TODO: When reorgs are handled, this will need to check whether the transaction
                // being added to the unmined collection was previously in a block.
                eventArgs.AddedTransactions.Add(Tuple.Create(tx, BlockIdentity.Unmined));
            }

            var removedUnmined = RecentTransactions.UnminedTransactions
                                 .Where(kvp => !changes.AllUnminedHashes.Contains(kvp.Key))
                                 .ToList(); // Collect to list so UnminedTransactions can be modified below.

            foreach (var unmined in removedUnmined)
            {
                // Transactions that were mined rather than being removed from the unmined
                // set due to a conflict have already been removed.
                RecentTransactions.UnminedTransactions.Remove(unmined.Key);
                RemoveTransactionFromTotals(unmined.Value, eventArgs.ModifiedAccountProperties);
                eventArgs.RemovedTransactions.Add(unmined.Value);
            }

            if (newChainTip != null)
            {
                ChainTip = newChainTip.Identity;
                eventArgs.NewChainTip = newChainTip.Identity;
            }

            OnChangesProcessed(eventArgs);
        }
コード例 #8
0
 private void OnChangesProcessed(ChangesProcessedEventArgs e)
 {
     ChangesProcessed?.Invoke(this, e);
 }