Beispiel #1
0
        public BalanceOperation(OrderedBalanceChange balanceChange, ChainBase chain)
        {
            ReceivedCoins = balanceChange.ReceivedCoins.ToList();
            SpentCoins    = balanceChange.SpentCoins.ToList();
            Amount        = balanceChange.Amount;
            TransactionId = balanceChange.TransactionId;

            if (balanceChange.BlockId != null)
            {
                BlockId       = balanceChange.BlockId;
                Height        = chain.GetBlock(balanceChange.BlockId).Height;
                Confirmations = (chain.Tip.Height - Height) + 1;
            }
        }
Beispiel #2
0
        private long GetScore(OrderedBalanceChange balance)
        {
            long score = 0;

            if (balance.BlockId != null)
            {
                score += 10;
                if (Chain.Contains(balance.BlockId))
                {
                    score += 100;
                }
            }
            return(score);
        }
Beispiel #3
0
        public void Broadcast(Transaction funding)
        {
            _ongoingTransactions.Add(funding);
            var indexer = CreateIndexer();

            if (!SkipIndexer)
            {
                indexer.Index(new TransactionEntry.Entity(null, funding, null));
                foreach (var entity in OrderedBalanceChange.ExtractScriptBalances(null, funding, null, null, 0))
                {
                    indexer.Index(new[] { entity });
                }
            }
            if (NewTransaction != null)
            {
                NewTransaction(funding);
            }
        }
        public void CanSerializeOrderedBalanceToEntity()
        {
            uint256 txId = new uint256(RandomUtils.GetBytes(32));
            Script script = CreateScript(512);
            OrderedBalanceChange balance = new OrderedBalanceChange(txId, script, null, null, 0);
            Assert.Equal(script, balance.ScriptPubKey);
            var entity = balance.ToEntity();
            Assert.False(entity.Properties.ContainsKey("h"));
            balance = new OrderedBalanceChange(entity);
            Assert.Equal(script, balance.ScriptPubKey);

            script = CreateScript(513);
            balance = new OrderedBalanceChange(txId, script, null, null, 0);
            Assert.Equal(script, balance.ScriptPubKey);
            entity = balance.ToEntity();
            Assert.True(entity.Properties.ContainsKey("h"));
            balance = new OrderedBalanceChange(entity);
            Assert.Equal(script, balance.ScriptPubKey);
        }
Beispiel #5
0
        private void UpdateHDState(OrderedBalanceChange entry)
        {
            var         repo       = Configuration.CreateWalletRepository();
            IDisposable walletLock = null;

            try
            {
                foreach (var matchedAddress in entry.MatchedRules.Select(m => WalletAddress.TryParse(m.Rule.CustomData)).Where(m => m != null))
                {
                    if (matchedAddress.HDKeySet == null)
                    {
                        return;
                    }
                    var keySet = repo.GetKeySetData(matchedAddress.WalletName, matchedAddress.HDKeySet.Name);
                    if (keySet == null)
                    {
                        return;
                    }
                    var keyIndex = (int)matchedAddress.HDKey.Path.Indexes.Last();
                    if (keyIndex < keySet.State.NextUnused)
                    {
                        return;
                    }
                    walletLock = walletLock ?? _WalletsSlimLock.LockWrite();
                    foreach (var address in repo.Scan(matchedAddress.WalletName, keySet, keyIndex + 1, 20))
                    {
                        ListenerTrace.Info("New wallet rule");
                        var walletEntry = address.CreateWalletRuleEntry();
                        _Wallets.Add(walletEntry);
                    }
                }
            }
            finally
            {
                if (walletLock != null)
                {
                    walletLock.Dispose();
                }
            }
        }
Beispiel #6
0
 private bool IsMature(OrderedBalanceChange c, ChainedBlock tip)
 {
     return(!c.IsCoinbase || (c.BlockId != null && IsMature(c.Height, tip)));
 }
Beispiel #7
0
        void node_MessageReceived(Node node, IncomingMessage message)
        {
            if (_KnownInvs.Count == 1000)
            {
                _KnownInvs.Clear();
            }
            if (message.Message.Payload is InvPayload)
            {
                var inv = (InvPayload)message.Message.Payload;
                foreach (var inventory in inv.Inventory)
                {
                    Transaction tx;
                    if (_Broadcasting.TryRemove(inventory.Hash, out tx))
                    {
                        ListenerTrace.Info("Broadcasted reached mempool " + inventory);
                    }
                }
                var getdata = new GetDataPayload(inv.Inventory.Where(i => i.Type == InventoryType.MSG_TX && _KnownInvs.TryAdd(i.Hash, i.Hash)).ToArray());
                foreach (var data in getdata.Inventory)
                {
                    data.Type = node.AddSupportedOptions(InventoryType.MSG_TX);
                }
                if (getdata.Inventory.Count > 0)
                {
                    node.SendMessageAsync(getdata);
                }
            }
            if (message.Message.Payload is TxPayload)
            {
                var tx = ((TxPayload)message.Message.Payload).Object;
                ListenerTrace.Verbose("Received Transaction " + tx.GetHash());
                _Indexer.IndexAsync(new TransactionEntry.Entity(tx.GetHash(), tx, null))
                .ContinueWith(HandleException);
                _Indexer.IndexOrderedBalanceAsync(tx)
                .ContinueWith(HandleException);
                Async(() =>
                {
                    var txId = tx.GetHash();
                    List <OrderedBalanceChange> balances;
                    using (_WalletsSlimLock.LockRead())
                    {
                        balances =
                            OrderedBalanceChange
                            .ExtractWalletBalances(txId, tx, null, null, int.MaxValue, _Wallets)
                            .AsEnumerable()
                            .ToList();
                    }
                    UpdateHDState(balances);

                    _Indexer.IndexAsync(balances)
                    .ContinueWith(HandleException);


                    Task notify = null;
                    using (_SubscriptionSlimLock.LockRead())
                    {
                        var topic = Configuration.Topics.SendNotifications;

                        notify = Task.WhenAll(_Subscriptions
                                              .GetNewTransactions()
                                              .Select(t => topic.AddAsync(new Notify()
                        {
                            SendAndForget = true,
                            Notification  = new Notification()
                            {
                                Subscription = t,
                                Data         = new NewTransactionNotificationData()
                                {
                                    TransactionId = txId
                                }
                            }
                        })).ToArray());
                    }
                    notify.Wait();
                });
                var unused = Configuration.Topics.NewTransactions.AddAsync(tx)
                             .ContinueWith(HandleException);
            }

            if (message.Message.Payload is BlockPayload)
            {
                var block   = ((BlockPayload)message.Message.Payload).Object;
                var blockId = block.GetHash();

                List <OrderedBalanceChange> balances = null;
                using (_WalletsSlimLock.LockRead())
                {
                    balances = block.Transactions.SelectMany(tx => OrderedBalanceChange.ExtractWalletBalances(null, tx, null, null, 0, _Wallets)).ToList();
                }
                UpdateHDState(balances);
            }

            if (message.Message.Payload is HeadersPayload)
            {
                if (_Chain.Tip.HashBlock != _LastChainTip)
                {
                    var header = _Chain.Tip.Header;
                    _LastChainTip = _Chain.Tip.HashBlock;

                    Configuration.Indexer.CreateIndexer().IndexChain(_Chain);

                    Async(() =>
                    {
                        CancellationTokenSource cancel = new CancellationTokenSource(TimeSpan.FromMinutes(30));
                        var repo = new CacheBlocksRepository(new NodeBlocksRepository(node));
                        TryLock(_LockBlocks, () =>
                        {
                            new IndexBlocksTask(Configuration.Indexer)
                            {
                                EnsureIsSetup = false,
                            }.Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Blocks), repo, _Chain)
                            {
                                CancellationToken = cancel.Token
                            }, _Indexer.TaskScheduler);
                        });
                        TryLock(_LockTransactions, () =>
                        {
                            new IndexTransactionsTask(Configuration.Indexer)
                            {
                                EnsureIsSetup = false
                            }
                            .Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Transactions), repo, _Chain)
                            {
                                CancellationToken = cancel.Token
                            }, _Indexer.TaskScheduler);
                        });
                        TryLock(_LockWallets, () =>
                        {
                            using (_WalletsSlimLock.LockRead())
                            {
                                new IndexBalanceTask(Configuration.Indexer, _Wallets)
                                {
                                    EnsureIsSetup = false
                                }
                                .Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Wallets), repo, _Chain)
                                {
                                    CancellationToken = cancel.Token
                                }, _Indexer.TaskScheduler);
                            }
                        });
                        TryLock(_LockBalance, () =>
                        {
                            new IndexBalanceTask(Configuration.Indexer, null)
                            {
                                EnsureIsSetup = false
                            }.Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Balances), repo, _Chain)
                            {
                                CancellationToken = cancel.Token
                            }, _Indexer.TaskScheduler);
                        });
                        TryLock(_LockSubscriptions, () =>
                        {
                            using (_SubscriptionSlimLock.LockRead())
                            {
                                new IndexNotificationsTask(Configuration, _Subscriptions)
                                {
                                    EnsureIsSetup = false,
                                }
                                .Index(new BlockFetcher(_Indexer.GetCheckpointRepository().GetCheckpoint("subscriptions"), repo, _Chain)
                                {
                                    CancellationToken = cancel.Token
                                }, _Indexer.TaskScheduler);
                            }
                        });
                        cancel.Dispose();
                        var unused = _Configuration.Topics.NewBlocks.AddAsync(header);
                    });
                }
            }
            if (message.Message.Payload is GetDataPayload)
            {
                var getData = (GetDataPayload)message.Message.Payload;
                foreach (var data in getData.Inventory)
                {
                    Transaction tx = null;
                    if (data.Type == InventoryType.MSG_TX && _Broadcasting.TryGetValue(data.Hash, out tx))
                    {
                        var payload = new TxPayload(tx);
                        node.SendMessageAsync(payload);
                        ListenerTrace.Info("Broadcasted " + data.Hash);
                    }
                }
            }
            if (message.Message.Payload is RejectPayload)
            {
                var     reject = (RejectPayload)message.Message.Payload;
                uint256 txId   = reject.Hash;
                if (txId != null)
                {
                    ListenerTrace.Info("Broadcasted transaction rejected (" + reject.Code + ") " + txId);
                    if (reject.Code != RejectCode.DUPLICATE)
                    {
                        Configuration.GetRejectTable().Create(txId.ToString(), reject);
                    }
                    Transaction tx;
                    _Broadcasting.TryRemove(txId, out tx);
                }
            }
        }
Beispiel #8
0
        void node_MessageReceived(Node node, IncomingMessage message)
        {
            if (message.Message.Payload is InvPayload)
            {
                var inv = (InvPayload)message.Message.Payload;
                foreach (var inventory in inv.Inventory.Where(i => _BroadcastedTransactions.ContainsKey(i.Hash)))
                {
                    ListenerTrace.Info("Broadcasted reached mempool " + inventory);
                }
                node.SendMessage(new GetDataPayload(inv.Inventory.ToArray()));
            }
            if (message.Message.Payload is TxPayload)
            {
                var tx = ((TxPayload)message.Message.Payload).Object;
                ListenerTrace.Verbose("Received Transaction " + tx.GetHash());
                RunTask("New transaction", () =>
                {
                    var txId = tx.GetHash();
                    _Indexer.Index(new TransactionEntry.Entity(txId, tx, null));
                    _Indexer.IndexOrderedBalance(tx);
                    RunTask("New transaction", () =>
                    {
                        var balances =
                            OrderedBalanceChange
                            .ExtractWalletBalances(txId, tx, null, null, int.MaxValue, _Wallets)
                            .GroupBy(b => b.PartitionKey);
                        foreach (var b in balances)
                        {
                            _Indexer.Index(b);
                        }
                    }, true);
                }, false);
            }
            if (message.Message.Payload is BlockPayload)
            {
                var block = ((BlockPayload)message.Message.Payload).Object;
                ListenerTrace.Info("Received block " + block.GetHash());
                RunTask("New block", () =>
                {
                    var blockId = block.GetHash();
                    node.SynchronizeChain(_Chain);
                    _Indexer.IndexChain(_Chain);
                    ListenerTrace.Info("New height : " + _Chain.Height);
                    var header = _Chain.GetBlock(blockId);
                    if (header == null)
                    {
                        return;
                    }
                    _Indexer.IndexWalletOrderedBalance(header.Height, block, _Wallets);

                    RunTask("New block", () =>
                    {
                        _Indexer.Index(block);
                    }, false);
                    RunTask("New block", () =>
                    {
                        _Indexer.IndexTransactions(header.Height, block);
                    }, false);
                    RunTask("New block", () =>
                    {
                        _Indexer.IndexOrderedBalance(header.Height, block);
                    }, false);
                }, true);
            }
            if (message.Message.Payload is PongPayload)
            {
                ListenerTrace.Verbose("Pong");
            }
        }
 private BalanceLocator Parse(string loc, OrderedBalanceChange[] changes, Dictionary<string, Transaction> txs)
 {
     if(loc.Contains("{"))
     {
         var res = Regex.Match(loc, "{(.*?)}");
         var tx = txs[res.Groups[1].Value];
         var change = changes.Single(c => c.TransactionId == tx.GetHash());
         return new UnconfirmedBalanceLocator(change.SeenUtc, tx.GetHash());
     }
     else
     {
         return BalanceLocator.Parse(loc.Substring(0, loc.Length - 2));
     }
 }
 private string GetName(Dictionary<string, Transaction> txs, OrderedBalanceChange change)
 {
     var name = txs.Single(t => t.Value.GetHash() == change.TransactionId).Key;
     var unconf1 = name.StartsWith("u");
     var unconf2 = change.BlockId == null;
     if(unconf1 != unconf2)
         Assert.False(true, "A confirmed or unconfirmed transaction should not have been returned");
     return name;
 }