Пример #1
0
        /// <summary>
        /// Remove old spent & confirmed TrackedOutpoint, old unconf operations, and old forked operations
        /// </summary>
        /// <param name="chain"></param>
        internal List <object> Prune(ConcurrentChain chain, int blockExpiration = 2000, TimeSpan?timeExpiration = null)
        {
            List <object> removed = new List <object>();

            timeExpiration = timeExpiration ?? TimeSpan.FromDays(7.0);
            foreach (var op in _Operations)
            {
                if (op.Value.BlockId != null)
                {
                    var chained  = chain.GetBlock(op.Value.BlockId);
                    var isForked = chained == null;
                    if (!isForked)
                    {
                        bool isOldConfirmed = chain.Height - chained.Height + 1 > blockExpiration;
                        if (isOldConfirmed)
                        {
                            foreach (var spent in op.Value.SpentCoins)                            //Stop tracking the outpoints
                            {
                                TrackedOutpoint unused;
                                if (_TrackedOutpoints.TryRemove(TrackedOutpoint.GetId(spent.Item1.Outpoint), out unused))
                                {
                                    removed.Add(unused);
                                }
                            }
                        }
                    }
                    else
                    {
                        var isOldFork = chain.Height - op.Value.Height + 1 > blockExpiration;
                        if (isOldFork)                        //clear any operation belonging to an old fork
                        {
                            Operation unused;
                            if (_Operations.TryRemove(op.Key, out unused))
                            {
                                removed.Add(unused);
                            }
                        }
                    }
                }
                else
                {
                    var isOldUnconf = (DateTimeOffset.UtcNow - op.Value.AddedDate) > timeExpiration;
                    if (isOldUnconf)                    //clear any old unconfirmed
                    {
                        Operation unused;
                        if (_Operations.TryRemove(op.Key, out unused))
                        {
                            removed.Add(unused);
                        }
                    }
                }
            }
            return(removed);
        }
Пример #2
0
        public bool NotifyTransaction(Transaction transaction, ChainedBlock chainedBlock, MerkleBlock proof)
        {
            if (chainedBlock != null)
            {
                if (proof == null)
                {
                    throw new ArgumentNullException("proof");
                }
                if (proof.Header.GetHash() != chainedBlock.Header.GetHash())
                {
                    throw new InvalidOperationException("The chained block and the merkle block are different blocks");
                }
                if (!proof.PartialMerkleTree.Check(chainedBlock.Header.HashMerkleRoot))
                {
                    throw new InvalidOperationException("The MerkleBlock does not have the expected merkle root");
                }
                if (!proof.PartialMerkleTree.GetMatchedTransactions().Contains(transaction.GetHash()))
                {
                    throw new InvalidOperationException("The MerkleBlock does not contains the input transaction");
                }
            }

            var interesting = false;

            lock (cs)
            {
                foreach (var txin in transaction.Inputs.AsIndexedInputs())
                {
                    var             key = TrackedOutpoint.GetId(txin.PrevOut);
                    TrackedOutpoint match;
                    if (_TrackedOutpoints.TryGetValue(key, out match))
                    {
                        TrackedScript parentMetadata;
                        if (_TrackedScripts.TryGetValue(match.TrackedScriptId, out parentMetadata))
                        {
                            interesting = true;
                            Spent(parentMetadata, txin, match.Coin, chainedBlock, proof);
                        }
                    }
                }
                foreach (var txout in transaction.Outputs.AsIndexedOutputs())
                {
                    var           key = TrackedScript.GetId(txout.TxOut.ScriptPubKey);
                    TrackedScript match;
                    if (_TrackedScripts.TryGetValue(key, out match))
                    {
                        interesting = true;
                        Received(match, txout, chainedBlock, proof);
                    }
                }
            }
            return(interesting);
        }
Пример #3
0
        private void Received(TrackedScript match, IndexedTxOut txout, ChainedBlock block, MerkleBlock proof)
        {
            var operation = new Operation(txout.Transaction, block, proof);

            SetUnconfirmedSeenIfPossible(txout.Transaction, block, operation);
            var coin = new Coin(txout);

            operation.ReceivedCoins.Add(Tuple.Create(coin, match.GetId()));
            _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation));
            var trackedOutpoint = new TrackedOutpoint()
            {
                Coin            = coin,
                TrackedScriptId = match.GetId(),
                Filter          = match.Filter
            };

            _TrackedOutpoints.TryAdd(trackedOutpoint.GetId(), trackedOutpoint);
        }
Пример #4
0
        private Operation Received(TrackedScript match, IndexedTxOut txout, ChainedBlock block, MerkleBlock proof)
        {
            var operation = new Operation(txout.Transaction, block, proof, _TrackedScripts);

            SetUnconfirmedSeenIfPossible(txout.Transaction, block, operation);
            var coin = new Coin(txout);

            operation.ReceivedCoins.Add(Tuple.Create(coin, match.GetId()));

            bool merged          = false;
            var  returned        = _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation, out merged));
            var  trackedOutpoint = new TrackedOutpoint()
            {
                Coin            = coin,
                TrackedScriptId = match.GetId(),
                Filter          = match.Filter
            };

            _TrackedOutpoints.TryAdd(trackedOutpoint.GetId(), trackedOutpoint);
            return((operation == returned || merged) ? operation : null);
        }
Пример #5
0
		private void Received(TrackedScript match, IndexedTxOut txout, ChainedBlock block, MerkleBlock proof)
		{
			var operation = new Operation(txout.Transaction, block, proof);
			SetUnconfirmedSeenIfPossible(txout.Transaction, block, operation);
			var coin = new Coin(txout);
			operation.ReceivedCoins.Add(Tuple.Create(coin, match.GetId()));
			_Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation));
			var trackedOutpoint = new TrackedOutpoint()
			{
				Coin = coin,
				TrackedScriptId = match.GetId(),
				Filter = match.Filter
			};
			_TrackedOutpoints.TryAdd(trackedOutpoint.GetId(), trackedOutpoint);
		}
Пример #6
0
		private Operation Received(TrackedScript match, IndexedTxOut txout, ChainedBlock block, MerkleBlock proof)
		{
			var operation = new Operation(txout.Transaction, block, proof, _TrackedScripts);
			SetUnconfirmedSeenIfPossible(txout.Transaction, block, operation);
			var coin = new Coin(txout);
			operation.ReceivedCoins.Add(Tuple.Create(coin, match.GetId()));

			bool merged = false;
			var returned = _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation, out merged));
			var trackedOutpoint = new TrackedOutpoint()
			{
				Coin = coin,
				TrackedScriptId = match.GetId(),
				Filter = match.Filter
			};
			_TrackedOutpoints.TryAdd(trackedOutpoint.GetId(), trackedOutpoint);
			return (operation == returned || merged) ? operation : null;
		}