コード例 #1
0
        public static bool HasIssuance(Transaction tx)
        {
            if (tx.Inputs.Count == 0)
            {
                return(false);
            }
            uint        markerPos = 0;
            ColorMarker marker    = ColorMarker.Get(tx, out markerPos);

            if (marker == null)
            {
                return(false);
            }
            if (!marker.HasValidQuantitiesCount(tx))
            {
                return(false);
            }

            for (uint i = 0; i < markerPos; i++)
            {
                ulong quantity = i >= marker.Quantities.Length ? 0 : marker.Quantities[i];
                if (quantity != 0)
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #2
0
        public static bool HasValidColorMarker(Transaction tx)
        {
            if (tx.Inputs.Count == 0 || tx.IsCoinBase)
            {
                return(false);
            }
            ColorMarker marker = Get(tx);

            if (marker == null)
            {
                return(false);
            }
            //If there are more items in the  asset quantity list  than the number of colorable outputs, the transaction is deemed invalid, and all outputs are uncolored.
            return(marker.HasValidQuantitiesCount(tx));
        }
コード例 #3
0
        public ColoredTransaction(uint256 txId, Transaction tx, ColoredCoin[] spentCoins, Script issuanceScriptPubkey)
            : this()
        {
            if (tx == null)
            {
                throw new ArgumentNullException("tx");
            }
            if (spentCoins == null)
            {
                throw new ArgumentNullException("spentCoins");
            }
            if (tx.IsCoinBase || tx.Inputs.Count == 0)
            {
                return;
            }
            txId = txId ?? tx.GetHash();

            var previousAssetQueue = new Queue <ColoredEntry>();

            for (uint i = 0; i < tx.Inputs.Count; i++)
            {
                TxIn        txin      = tx.Inputs[i];
                ColoredCoin prevAsset = spentCoins.FirstOrDefault(s => s.Outpoint == txin.PrevOut);
                if (prevAsset != null)
                {
                    var input = new ColoredEntry()
                    {
                        Index = i,
                        Asset = prevAsset.Amount
                    };
                    previousAssetQueue.Enqueue(input);
                    this.Inputs.Add(input);
                }
            }

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

            if (marker == null)
            {
                return;
            }

            this.Marker = marker;
            if (!marker.HasValidQuantitiesCount(tx))
            {
                return;
            }

            AssetId issuedAsset = null;

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

                if (issuedAsset == null)
                {
                    TxIn txIn = tx.Inputs.FirstOrDefault();
                    if (txIn == null)
                    {
                        continue;
                    }
                    if (issuanceScriptPubkey == null)
                    {
                        throw new ArgumentException("The transaction has an issuance detected, but issuanceScriptPubkey is null.", "issuanceScriptPubkey");
                    }
                    issuedAsset = issuanceScriptPubkey.Hash.ToAssetId();
                }
                entry.Asset = new AssetMoney(issuedAsset, entry.Asset.Quantity);
                this.Issuances.Add(entry);
            }

            long 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 = new AssetMoney(entry.Asset.Id, (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)
                {
                    this.Transfers.Clear();
                    this.Issuances.Clear();
                    return;
                }
                entry.Asset = new AssetMoney(previousAssetQueue.Peek().Asset.Id, entry.Asset.Quantity);
                long remaining = entry.Asset.Quantity;
                while (remaining != 0)
                {
                    if (previousAssetQueue.Count == 0 || previousAssetQueue.Peek().Asset.Id != entry.Asset.Id)
                    {
                        this.Transfers.Clear();
                        this.Issuances.Clear();
                        return;
                    }
                    long assertPart = Math.Min(previousAssetQueue.Peek().Asset.Quantity - used, remaining);
                    remaining = remaining - assertPart;
                    used     += assertPart;
                    if (used == previousAssetQueue.Peek().Asset.Quantity)
                    {
                        previousAssetQueue.Dequeue();
                        used = 0;
                    }
                }

                this.Transfers.Add(entry);
            }
        }