Esempio n. 1
0
        public async Task <bool> EnsureColoredTransactionLoadedAsync(IColoredTransactionRepository repository)
        {
            if (ColoredTransaction != null)
            {
                this.UpdateToColoredCoins();
                return(true);
            }
            if (!(repository is CachedColoredTransactionRepository))
            {
                repository = new CachedColoredTransactionRepository(repository);
            }
            var tx = await repository.Transactions.GetAsync(TransactionId).ConfigureAwait(false);

            if (tx == null)
            {
                return(false);
            }
            try
            {
                var color = await tx.GetColoredTransactionAsync(repository).ConfigureAwait(false);

                if (color == null)
                {
                    return(false);
                }
                ColoredTransaction = color;
                this.UpdateToColoredCoins();
                return(true);
            }
            catch (TransactionNotFoundException)
            {
                return(false);
            }
        }
		public CachedColoredTransactionRepository(IColoredTransactionRepository inner)
		{
			if(inner == null)
				throw new ArgumentNullException("inner");
			_Inner = inner;
			_InnerTransactionRepository = new CachedTransactionRepository(inner.Transactions);
		}
Esempio n. 3
0
        private static async Task <bool> BulkLoadIfCached(Transaction transaction, IColoredTransactionRepository repo)
        {
            if (!(repo is CachedColoredTransactionRepository))
            {
                return(false);
            }
            var hasIssuance = HasIssuance(transaction);

            repo = new NoDuplicateColoredTransactionRepository(repo); //prevent from having concurrent request to the same transaction id
            var all = Enumerable
                      .Range(0, transaction.Inputs.Count)
                      .Select(async i =>
            {
                var txId   = transaction.Inputs[i].PrevOut.Hash;
                var result = await repo.GetAsync(txId).ConfigureAwait(false);
                if (result == null || (i == 0 && hasIssuance))
                {
                    await repo.Transactions.GetAsync(txId).ConfigureAwait(false);
                }
            })
                      .ToArray();
            await Task.WhenAll(all).ConfigureAwait(false);

            return(true);
        }
 public NoDuplicateColoredTransactionRepository(IColoredTransactionRepository inner)
 {
     if (inner == null)
     {
         throw new ArgumentNullException("inner");
     }
     _Inner = inner;
 }
Esempio n. 5
0
 public CachedColoredTransactionRepository(IColoredTransactionRepository inner)
 {
     if (inner == null)
     {
         throw new ArgumentNullException("inner");
     }
     _Inner = inner;
     _InnerTransactionRepository = new CachedTransactionRepository(inner.Transactions);
 }
Esempio n. 6
0
 private static IColoredTransactionRepository EnsureCachedRepository(IColoredTransactionRepository repo)
 {
     if (repo is CachedColoredTransactionRepository)
     {
         return(repo);
     }
     repo = new CachedColoredTransactionRepository(repo);
     return(repo);
 }
Esempio n. 7
0
 public CachedColoredTransactionRepository(IColoredTransactionRepository inner)
 {
     if (inner == null)
     {
         throw new ArgumentNullException("inner");
     }
     this._Inner                = inner;
     this.Transactions          = new CachedTransactionRepository(inner.Transactions);
     this.MaxCachedTransactions = 1000;
 }
Esempio n. 8
0
        public static IEnumerable <ColoredCoin> Find(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
        {
            if (txId == null)
            {
                txId = tx.GetHash();
            }
            var colored = tx.GetColoredTransaction(repo);

            return(Find(txId, tx, colored));
        }
Esempio n. 9
0
		public static async Task<ColoredTransaction> GetColoredTransactionAsync(this Transaction tx, IColoredTransactionRepository repo)
		{
			try
			{
				return await ColoredTransaction.FetchColorsAsync(tx, repo).ConfigureAwait(false);
			}
			catch(TransactionNotFoundException)
			{
				return null;
			}
		}
Esempio n. 10
0
        public static ColoredTransaction FetchColors(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
        {
            txId = txId ?? tx.GetHash();
            var result = repo.Get(txId);

            if (result != null)
            {
                return(result);
            }

            ColoredTransaction lastColored = null;

            //The following code is to prevent recursion of FetchColors that would fire a StackOverflow if the origin of traded asset were deep in the transaction dependency tree
            repo = EnsureCachedRepository(repo);
            HashSet <uint256> invalidColored = new HashSet <uint256>();
            Stack <Tuple <uint256, Transaction> > ancestors = new Stack <Tuple <uint256, Transaction> >();

            ancestors.Push(Tuple.Create(txId, tx));
            while (ancestors.Count != 0)
            {
                var peek = ancestors.Peek();
                txId = peek.Item1;
                tx   = peek.Item2;
                bool isComplete = true;
                if (!tx.HasValidColoredMarker() && ancestors.Count != 1)
                {
                    invalidColored.Add(txId);
                    ancestors.Pop();
                    continue;
                }

                for (int i = 0; i < tx.Inputs.Count; i++)
                {
                    var txin = tx.Inputs[i];
                    if (repo.Get(txin.PrevOut.Hash) == null && !invalidColored.Contains(txin.PrevOut.Hash))
                    {
                        var prevTx = repo.Transactions.Get(txin.PrevOut.Hash);
                        if (prevTx == null)
                        {
                            throw new TransactionNotFoundException("Transaction " + txin.PrevOut.Hash + " not found in transaction repository", txId);
                        }
                        ancestors.Push(Tuple.Create(txin.PrevOut.Hash, prevTx));
                        isComplete = false;
                    }
                }
                if (isComplete)
                {
                    lastColored = FetchColorsWithAncestorsSolved(txId, tx, repo);
                    ancestors.Pop();
                }
            }

            return(lastColored);
        }
 public static void Put(this IColoredTransactionRepository repo, uint256 txId, ColoredTransaction tx)
 {
     try
     {
         repo.PutAsync(txId, tx).Wait();
     }
     catch (AggregateException aex)
     {
         ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
     }
 }
Esempio n. 12
0
		public static ColoredTransaction GetColoredTransaction(this Transaction tx, IColoredTransactionRepository repo)
		{
			try
			{
				return tx.GetColoredTransactionAsync(repo).Result;
			}
			catch(AggregateException aex)
			{
				ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
				return null;
			}
		}
Esempio n. 13
0
 public static async Task <ColoredTransaction> GetColoredTransactionAsync(this Transaction tx,
                                                                          IColoredTransactionRepository repo)
 {
     try
     {
         return(await ColoredTransaction.FetchColorsAsync(tx, repo).ConfigureAwait(false));
     }
     catch (TransactionNotFoundException)
     {
         return(null);
     }
 }
Esempio n. 14
0
 public static ColoredTransaction FetchColors(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
 {
     try
     {
         return(FetchColorsAsync(txId, tx, repo).Result);
     }
     catch (AggregateException aex)
     {
         ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
         return(null);
     }
 }
 public static ColoredTransaction Get(this IColoredTransactionRepository repo, uint256 txId)
 {
     try
     {
         return(repo.GetAsync(txId).Result);
     }
     catch (AggregateException aex)
     {
         ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
         return(null);
     }
 }
Esempio n. 16
0
 public static ColoredTransaction GetColoredTransaction(this Transaction tx, IColoredTransactionRepository repo)
 {
     try
     {
         return(tx.GetColoredTransactionAsync(repo).Result);
     }
     catch (AggregateException aex)
     {
         ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
         return(null);
     }
 }
Esempio n. 17
0
        public static ColoredTransaction FetchColors(uint256 txId, IColoredTransactionRepository repo)
        {
            if (repo == null)
            {
                throw new ArgumentNullException("repo");
            }
            repo = EnsureCachedRepository(repo);
            var colored = repo.Get(txId);

            if (colored != null)
            {
                return(colored);
            }
            var tx = repo.Transactions.Get(txId);

            if (tx == null)
            {
                throw new TransactionNotFoundException("Transaction " + txId + " not found in transaction repository", txId);
            }
            return(FetchColors(txId, tx, repo));
        }
Esempio n. 18
0
		private static async Task<bool> BulkLoadIfCached(Transaction transaction, IColoredTransactionRepository repo)
		{
			if(!(repo is CachedColoredTransactionRepository))
				return false;
			var hasIssuance = HasIssuance(transaction);
			repo = new NoDuplicateColoredTransactionRepository(repo); //prevent from having concurrent request to the same transaction id
			var all = Enumerable
				.Range(0, transaction.Inputs.Count)
				.Select(async i =>
				{
					var txId = transaction.Inputs[i].PrevOut.Hash;
					var result = await repo.GetAsync(txId).ConfigureAwait(false);
					if(result == null || (i == 0 && hasIssuance))
						await repo.Transactions.GetAsync(txId).ConfigureAwait(false);
				})
				.ToArray();
			await Task.WhenAll(all).ConfigureAwait(false);
			return true;
		}
Esempio n. 19
0
		public static Task<ColoredTransaction> FetchColorsAsync(Transaction tx, IColoredTransactionRepository repo)
		{
			return FetchColorsAsync(null, tx, repo);
		}
Esempio n. 20
0
		public static IEnumerable<ColoredCoin> Find(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
		{
			if(txId == null)
				txId = tx.GetHash();
			var colored = tx.GetColoredTransaction(repo);
			return Find(txId, tx, colored);
		}
Esempio n. 21
0
		public static async Task<ColoredTransaction> FetchColorsAsync(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
		{
			if(repo == null)
				throw new ArgumentNullException("repo");
			if(txId == null)
			{
				if(tx == null)
					throw new ArgumentException("txId or tx should be different of null");
				txId = tx.GetHash();
			}
			//The following code is to prevent recursion of FetchColors that would fire a StackOverflow if the origin of traded asset were deep in the transaction dependency tree
			var colored = await repo.GetAsync(txId).ConfigureAwait(false);
			if(colored != null)
				return colored;

			Stack<ColoredFrame> frames = new Stack<ColoredFrame>();
			Stack<ColoredTransaction> coloreds = new Stack<ColoredTransaction>();
			frames.Push(new ColoredFrame()
			{
				TransactionId = txId,
				Transaction = tx
			});
			while(frames.Count != 0)
			{
				var frame = frames.Pop();
				colored = frame.PreviousTransactions != null ? null : await repo.GetAsync(frame.TransactionId).ConfigureAwait(false); //Already known
				if(colored != null)
				{
					coloreds.Push(colored);
					continue;
				}
				frame.Transaction = frame.Transaction ?? await repo.Transactions.GetAsync(frame.TransactionId).ConfigureAwait(false);
				if(frame.Transaction == null)
					throw new TransactionNotFoundException("Transaction " + frame.TransactionId + " not found in transaction repository", frame.TransactionId);
				if(frame.PreviousTransactions == null)
				{
					if(!frame.Transaction.HasValidColoredMarker()
					&& frame.TransactionId != txId) //We care about destroyed asset, if this is the requested transaction
					{
						coloreds.Push(new ColoredTransaction());
						continue;
					}
					frame.PreviousTransactions = new ColoredTransaction[frame.Transaction.Inputs.Count];
					await BulkLoadIfCached(frame.Transaction, repo).ConfigureAwait(false);
					frames.Push(frame);
					for(int i = 0 ; i < frame.Transaction.Inputs.Count ; i++)
					{
						frames.Push(new ColoredFrame()
						{
							TransactionId = frame.Transaction.Inputs[i].PrevOut.Hash
						});
					}
					frame.Transaction = frame.TransactionId == txId ? frame.Transaction : null; //Do not waste memory, will refetch later
					continue;
				}
				else
				{
					for(int i = 0 ; i < frame.Transaction.Inputs.Count ; i++)
					{
						frame.PreviousTransactions[i] = coloreds.Pop();
					}
				}

				Script issuanceScriptPubkey = null;
				if(HasIssuance(frame.Transaction))
				{
					var txIn = frame.Transaction.Inputs[0];
					var previous = await repo.Transactions.GetAsync(txIn.PrevOut.Hash).ConfigureAwait(false);
					if(previous == null)
					{
						throw new TransactionNotFoundException("An open asset transaction is issuing assets, but it needs a parent transaction in the TransactionRepository to know the address of the issued asset (missing : " + txIn.PrevOut.Hash + ")", txIn.PrevOut.Hash);
					}
					if(txIn.PrevOut.N < previous.Outputs.Count)
						issuanceScriptPubkey = previous.Outputs[txIn.PrevOut.N].ScriptPubKey;
				}

				List<ColoredCoin> spentCoins = new List<ColoredCoin>();
				for(int i = 0 ; i < frame.Transaction.Inputs.Count ; i++)
				{
					var txIn = frame.Transaction.Inputs[i];
					var entry = frame.PreviousTransactions[i].GetColoredEntry(txIn.PrevOut.N);
					if(entry != null)
						spentCoins.Add(new ColoredCoin(entry.Asset, new Coin(txIn.PrevOut, new TxOut())));
				}
				colored = new ColoredTransaction(frame.TransactionId, frame.Transaction, spentCoins.ToArray(), issuanceScriptPubkey);
				coloreds.Push(colored);
				await repo.PutAsync(frame.TransactionId, colored).ConfigureAwait(false);
			}
			if(coloreds.Count != 1)
				throw new InvalidOperationException("Colored stack length != 1, this is a NBitcoin bug, please contact us.");
			return coloreds.Pop();
		}
Esempio n. 22
0
 public static ColoredTransaction GetColoredTransaction(this Transaction tx, IColoredTransactionRepository repo)
 {
     return(tx.GetColoredTransactionAsync(repo).GetAwaiter().GetResult());
 }
Esempio n. 23
0
 public static ColoredTransaction FetchColors(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
 {
     return(FetchColorsAsync(txId, tx, repo).GetAwaiter().GetResult());
 }
Esempio n. 24
0
 public static ColoredTransaction FetchColors(Transaction tx, IColoredTransactionRepository repo)
 {
     return(FetchColors(null, tx, repo));
 }
Esempio n. 25
0
		public static ColoredTransaction FetchColors(uint256 txId, IColoredTransactionRepository repo)
		{
			return FetchColors(txId, null, repo);
		}
Esempio n. 26
0
        public static async Task <ColoredTransaction> FetchColorsAsync(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
        {
            if (repo == null)
            {
                throw new ArgumentNullException("repo");
            }
            repo = EnsureCachedRepository(repo);

            ColoredTransaction result = null;

            if (txId != null)
            {
                result = await repo.GetAsync(txId).ConfigureAwait(false);
            }
            else
            {
                if (tx == null)
                {
                    throw new ArgumentException("txId or tx should be different of null");
                }
                txId   = tx.GetHash();
                result = await repo.GetAsync(txId).ConfigureAwait(false);
            }
            if (result != null)
            {
                return(result);
            }

            if (tx == null)
            {
                tx = await repo.Transactions.GetAsync(txId).ConfigureAwait(false);

                if (tx == null)
                {
                    throw new TransactionNotFoundException("Transaction " + txId + " not found in transaction repository", txId);
                }
            }


            ColoredTransaction lastColored = null;
            //The following code is to prevent recursion of FetchColors that would fire a StackOverflow if the origin of traded asset were deep in the transaction dependency tree
            HashSet <uint256> invalidColored = new HashSet <uint256>();
            Stack <Tuple <uint256, Transaction> > ancestors = new Stack <Tuple <uint256, Transaction> >();

            ancestors.Push(Tuple.Create(txId, tx));
            while (ancestors.Count != 0)
            {
                var peek = ancestors.Peek();
                txId = peek.Item1;
                tx   = peek.Item2;
                bool isComplete = true;
                if (!tx.HasValidColoredMarker() && ancestors.Count != 1)
                {
                    invalidColored.Add(txId);
                    ancestors.Pop();
                    continue;
                }

                var parentsToResolve =
                    Enumerable
                    .Range(0, tx.Inputs.Count)
                    .Select(async i =>
                {
                    var txin  = tx.Inputs[i];
                    var color = await repo.GetAsync(txin.PrevOut.Hash).ConfigureAwait(false);
                    if (color == null && !invalidColored.Contains(txin.PrevOut.Hash))
                    {
                        var prevTx = await repo.Transactions.GetAsync(txin.PrevOut.Hash).ConfigureAwait(false);
                        if (prevTx == null)
                        {
                            throw new TransactionNotFoundException("Transaction " + txin.PrevOut.Hash + " not found in transaction repository", txId);
                        }
                        return(Tuple.Create(txin.PrevOut.Hash, prevTx));
                    }
                    return(null);
                }).ToArray();

                foreach (var parent in parentsToResolve)
                {
                    var toResolve = await parent.ConfigureAwait(false);

                    if (toResolve != null)
                    {
                        ancestors.Push(toResolve);
                        isComplete = false;
                    }
                }


                if (isComplete)
                {
                    lastColored = await FetchColorsWithAncestorsSolved(txId, tx, (CachedColoredTransactionRepository)repo).ConfigureAwait(false);

                    await repo.PutAsync(txId, lastColored).ConfigureAwait(false);

                    ancestors.Pop();
                }
            }

            return(lastColored);
        }
Esempio n. 27
0
 public static Task <ColoredTransaction> FetchColorsAsync(Transaction tx, IColoredTransactionRepository repo)
 {
     return(FetchColorsAsync(null, tx, repo));
 }
Esempio n. 28
0
        public static async Task <ColoredTransaction> FetchColorsAsync(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
        {
            if (repo == null)
            {
                throw new ArgumentNullException("repo");
            }
            if (txId == null)
            {
                if (tx == null)
                {
                    throw new ArgumentException("txId or tx should be different of null");
                }
                txId = tx.GetHash();
            }
            //The following code is to prevent recursion of FetchColors that would fire a StackOverflow if the origin of traded asset were deep in the transaction dependency tree
            var colored = await repo.GetAsync(txId).ConfigureAwait(false);

            if (colored != null)
            {
                return(colored);
            }

            Stack <ColoredFrame>       frames   = new Stack <ColoredFrame>();
            Stack <ColoredTransaction> coloreds = new Stack <ColoredTransaction>();

            frames.Push(new ColoredFrame()
            {
                TransactionId = txId,
                Transaction   = tx
            });
            while (frames.Count != 0)
            {
                var frame = frames.Pop();
                colored = frame.PreviousTransactions != null ? null : await repo.GetAsync(frame.TransactionId).ConfigureAwait(false); //Already known

                if (colored != null)
                {
                    coloreds.Push(colored);
                    continue;
                }
                frame.Transaction = frame.Transaction ?? await repo.Transactions.GetAsync(frame.TransactionId).ConfigureAwait(false);

                if (frame.Transaction == null)
                {
                    throw new TransactionNotFoundException("Transaction " + frame.TransactionId + " not found in transaction repository", frame.TransactionId);
                }
                if (frame.PreviousTransactions == null)
                {
                    if (frame.Transaction.IsCoinBase ||
                        (!frame.Transaction.HasValidColoredMarker() &&
                         frame.TransactionId != txId)) //We care about destroyed asset, if this is the requested transaction
                    {
                        coloreds.Push(new ColoredTransaction());
                        continue;
                    }
                    frame.PreviousTransactions = new ColoredTransaction[frame.Transaction.Inputs.Count];
                    await BulkLoadIfCached(frame.Transaction, repo).ConfigureAwait(false);

                    frames.Push(frame);
                    for (int i = 0; i < frame.Transaction.Inputs.Count; i++)
                    {
                        frames.Push(new ColoredFrame()
                        {
                            TransactionId = frame.Transaction.Inputs[i].PrevOut.Hash
                        });
                    }
                    frame.Transaction = frame.TransactionId == txId ? frame.Transaction : null; //Do not waste memory, will refetch later
                    continue;
                }
                else
                {
                    for (int i = 0; i < frame.Transaction.Inputs.Count; i++)
                    {
                        frame.PreviousTransactions[i] = coloreds.Pop();
                    }
                }

                Script issuanceScriptPubkey = null;
                if (HasIssuance(frame.Transaction))
                {
                    var txIn     = frame.Transaction.Inputs[0];
                    var previous = await repo.Transactions.GetAsync(txIn.PrevOut.Hash).ConfigureAwait(false);

                    if (previous == null)
                    {
                        throw new TransactionNotFoundException("An open asset transaction is issuing assets, but it needs a parent transaction in the TransactionRepository to know the address of the issued asset (missing : " + txIn.PrevOut.Hash + ")", txIn.PrevOut.Hash);
                    }
                    if (txIn.PrevOut.N < previous.Outputs.Count)
                    {
                        issuanceScriptPubkey = previous.Outputs[txIn.PrevOut.N].ScriptPubKey;
                    }
                }

                List <ColoredCoin> spentCoins = new List <ColoredCoin>();
                for (int i = 0; i < frame.Transaction.Inputs.Count; i++)
                {
                    var txIn  = frame.Transaction.Inputs[i];
                    var entry = frame.PreviousTransactions[i].GetColoredEntry(txIn.PrevOut.N);
                    if (entry != null)
                    {
                        spentCoins.Add(new ColoredCoin(entry.Asset, new Coin(txIn.PrevOut, new TxOut())));
                    }
                }
                colored = new ColoredTransaction(frame.TransactionId, frame.Transaction, spentCoins.ToArray(), issuanceScriptPubkey);
                coloreds.Push(colored);
                await repo.PutAsync(frame.TransactionId, colored).ConfigureAwait(false);
            }
            if (coloreds.Count != 1)
            {
                throw new InvalidOperationException("Colored stack length != 1, this is a NBitcoin bug, please contact us.");
            }
            return(coloreds.Pop());
        }
 public static ColoredTransaction Get(this IColoredTransactionRepository repo, uint256 txId)
 {
     return(repo.GetAsync(txId).GetAwaiter().GetResult());
 }
Esempio n. 30
0
 public static ColoredTransaction FetchColors(uint256 txId, IColoredTransactionRepository repo)
 {
     return(FetchColors(txId, null, repo));
 }
Esempio n. 31
0
		public static ColoredTransaction FetchColors(Transaction tx, IColoredTransactionRepository repo)
		{
			return FetchColors(null, tx, repo);
		}
 public static Task <ColoredTransaction> GetAsync(this IColoredTransactionRepository repo, string txId)
 {
     return(repo.GetAsync(uint256.Parse(txId)));
 }
Esempio n. 33
0
		public static Task<ColoredTransaction> FetchColorsAsync(uint256 txId, IColoredTransactionRepository repo)
		{
			return FetchColorsAsync(txId, null, repo);
		}
Esempio n. 34
0
		public static async Task<ColoredTransaction> FetchColorsAsync(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
		{
			if(repo == null)
				throw new ArgumentNullException("repo");
			repo = EnsureCachedRepository(repo);

			ColoredTransaction result = null;
			if(txId != null)
			{
				result = await repo.GetAsync(txId).ConfigureAwait(false);
			}
			else
			{
				if(tx == null)
					throw new ArgumentException("txId or tx should be different of null");
				txId = tx.GetHash();
				result = await repo.GetAsync(txId).ConfigureAwait(false);
			}
			if(result != null)
				return result;

			if(tx == null)
			{
				tx = await repo.Transactions.GetAsync(txId).ConfigureAwait(false);
				if(tx == null)
					throw new TransactionNotFoundException("Transaction " + txId + " not found in transaction repository", txId);
			}


			ColoredTransaction lastColored = null;
			//The following code is to prevent recursion of FetchColors that would fire a StackOverflow if the origin of traded asset were deep in the transaction dependency tree
			HashSet<uint256> invalidColored = new HashSet<uint256>();
			Stack<Tuple<uint256, Transaction>> ancestors = new Stack<Tuple<uint256, Transaction>>();
			ancestors.Push(Tuple.Create(txId, tx));
			while(ancestors.Count != 0)
			{
				var peek = ancestors.Peek();
				txId = peek.Item1;
				tx = peek.Item2;
				bool isComplete = true;
				if(!tx.HasValidColoredMarker() && ancestors.Count != 1)
				{
					invalidColored.Add(txId);
					ancestors.Pop();
					continue;
				}

				var parentsToResolve =
					Enumerable
					.Range(0, tx.Inputs.Count)
					.Select(async i =>
				{
					var txin = tx.Inputs[i];
					var color = await repo.GetAsync(txin.PrevOut.Hash).ConfigureAwait(false);
					if(color == null && !invalidColored.Contains(txin.PrevOut.Hash))
					{
						var prevTx = await repo.Transactions.GetAsync(txin.PrevOut.Hash).ConfigureAwait(false);
						if(prevTx == null)
							throw new TransactionNotFoundException("Transaction " + txin.PrevOut.Hash + " not found in transaction repository", txId);
						return Tuple.Create(txin.PrevOut.Hash, prevTx);
					}
					return null;
				}).ToArray();

				foreach(var parent in parentsToResolve)
				{
					var toResolve = await parent.ConfigureAwait(false);
					if(toResolve != null)
					{
						ancestors.Push(toResolve);
						isComplete = false;
					}
				}


				if(isComplete)
				{
					lastColored = await FetchColorsWithAncestorsSolved(txId, tx, (CachedColoredTransactionRepository)repo).ConfigureAwait(false);
					await repo.PutAsync(txId, lastColored).ConfigureAwait(false);
					ancestors.Pop();
				}
			}

			return lastColored;
		}
Esempio n. 35
0
		public static ColoredTransaction FetchColors(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
		{
			try
			{
				return FetchColorsAsync(txId, tx, repo).Result;
			}
			catch(AggregateException aex)
			{
				ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
				return null;
			}
		}
Esempio n. 36
0
		private static IColoredTransactionRepository EnsureCachedRepository(IColoredTransactionRepository repo)
		{
			if(repo is CachedColoredTransactionRepository)
				return repo;
			repo = new CachedColoredTransactionRepository(new NoDuplicateColoredTransactionRepository(repo));
			return repo;
		}
Esempio n. 37
0
 public static IEnumerable <ColoredCoin> Find(Transaction tx, IColoredTransactionRepository repo)
 {
     return(Find(null, tx, repo));
 }
 public static void Put(this IColoredTransactionRepository repo, uint256 txId, ColoredTransaction tx)
 {
     repo.PutAsync(txId, tx).GetAwaiter().GetResult();
 }
 public static ColoredTransaction Get(this IColoredTransactionRepository repo, string txId)
 {
     return(repo.Get(uint256.Parse(txId)));
 }
Esempio n. 40
0
		public static IEnumerable<ColoredCoin> Find(Transaction tx, IColoredTransactionRepository repo)
		{
			return Find(null, tx, repo);
		}
Esempio n. 41
0
 public static Task <ColoredTransaction> FetchColorsAsync(uint256 txId, IColoredTransactionRepository repo)
 {
     return(FetchColorsAsync(txId, null, repo));
 }
 public async Task<bool> EnsureColoredTransactionLoadedAsync(IColoredTransactionRepository repository)
 {
     if(ColoredTransaction != null)
     {
         this.UpdateToColoredCoins();
         return true;
     }
     if(!(repository is CachedColoredTransactionRepository))
         repository = new CachedColoredTransactionRepository(repository);
     var tx = await repository.Transactions.GetAsync(TransactionId).ConfigureAwait(false);
     if(tx == null)
         return false;
     try
     {
         var color = await tx.GetColoredTransactionAsync(repository).ConfigureAwait(false);
         if(color == null)
             return false;
         ColoredTransaction = color;
         this.UpdateToColoredCoins();
         return true;
     }
     catch(TransactionNotFoundException)
     {
         return false;
     }
 }
Esempio n. 43
0
 public static ColoredTransaction GetColoredTransaction(this Transaction tx, IColoredTransactionRepository repo)
 {
     return(ColoredTransaction.FetchColors(tx, repo));
 }
Esempio n. 44
0
        private static ColoredTransaction FetchColorsWithAncestorsSolved(uint256 txId, Transaction tx, IColoredTransactionRepository repo)
        {
            ColoredTransaction colored = new ColoredTransaction();

            Queue <ColoredEntry> previousAssetQueue = new Queue <ColoredEntry>();

            for (uint i = 0; i < tx.Inputs.Count; i++)
            {
                var txin        = tx.Inputs[i];
                var prevColored = repo.Get(txin.PrevOut.Hash);
                if (prevColored == null)
                {
                    continue;
                }
                var prevAsset = prevColored.GetColoredEntry(txin.PrevOut.N);
                if (prevAsset != null)
                {
                    var input = new ColoredEntry()
                    {
                        Index = i,
                        Asset = prevAsset.Asset
                    };
                    previousAssetQueue.Enqueue(input);
                    colored.Inputs.Add(input);
                }
            }

            uint markerPos = 0;
            var  marker    = ColorMarker.Get(tx, out markerPos);

            if (marker == null)
            {
                repo.Put(txId, colored);
                return(colored);
            }
            colored.Marker = marker;
            if (!marker.HasValidQuantitiesCount(tx))
            {
                repo.Put(txId, colored);
                return(colored);
            }

            AssetId issuedAsset = null;

            for (uint i = 0; i < markerPos; i++)
            {
                var entry = new ColoredEntry();
                entry.Index          = i;
                entry.Asset.Quantity = i >= marker.Quantities.Length ? 0 : marker.Quantities[i];
                if (entry.Asset.Quantity == 0)
                {
                    continue;
                }

                if (issuedAsset == null)
                {
                    var txIn = tx.Inputs.FirstOrDefault();
                    if (txIn == null)
                    {
                        continue;
                    }
                    var prev = repo.Transactions.Get(txIn.PrevOut.Hash);
                    if (prev == null)
                    {
                        throw new TransactionNotFoundException("This open asset transaction is issuing assets, but it needs a parent transaction in the TransactionRepository to know the address of the issued asset (missing : " + txIn.PrevOut.Hash + ")", txIn.PrevOut.Hash);
                    }
                    issuedAsset = prev.Outputs[(int)txIn.PrevOut.N].ScriptPubKey.Hash.ToAssetId();
                }
                entry.Asset.Id = issuedAsset;
                colored.Issuances.Add(entry);
            }

            ulong used = 0;

            for (uint i = markerPos + 1; i < tx.Outputs.Count; i++)
            {
                var entry = new ColoredEntry();
                entry.Index = i;
                //If there are less items in the  asset quantity list  than the number of colorable outputs (all the outputs except the marker output), the outputs in excess receive an asset quantity of zero.
                entry.Asset.Quantity = (i - 1) >= marker.Quantities.Length ? 0 : marker.Quantities[i - 1];
                if (entry.Asset.Quantity == 0)
                {
                    continue;
                }

                //If there are less asset units in the input sequence than in the output sequence, the transaction is considered invalid and all outputs are uncolored.
                if (previousAssetQueue.Count == 0)
                {
                    colored.Transfers.Clear();
                    colored.Issuances.Clear();
                    repo.Put(txId, colored);
                    return(colored);
                }
                entry.Asset.Id = previousAssetQueue.Peek().Asset.Id;
                var remaining = entry.Asset.Quantity;
                while (remaining != 0)
                {
                    if (previousAssetQueue.Count == 0 || previousAssetQueue.Peek().Asset.Id != entry.Asset.Id)
                    {
                        colored.Transfers.Clear();
                        colored.Issuances.Clear();
                        repo.Put(txId, colored);
                        return(colored);
                    }
                    var assertPart = Math.Min(previousAssetQueue.Peek().Asset.Quantity - used, remaining);
                    remaining = remaining - assertPart;
                    used     += assertPart;
                    if (used == previousAssetQueue.Peek().Asset.Quantity)
                    {
                        previousAssetQueue.Dequeue();
                        used = 0;
                    }
                }
                colored.Transfers.Add(entry);
            }
            repo.Put(txId, colored);
            return(colored);
        }