Ejemplo n.º 1
0
 public bool Run()
 {
     Json.Deserialize(new MemoryStream(UTF8NoBOM.GetBytes(JSONInput)));
     return(true);
 }
        private BOLT11PaymentRequest(string str, Network network)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }
            if (network == null)
            {
                throw new ArgumentNullException(nameof(network));
            }
            if (str.StartsWith("lightning:", StringComparison.OrdinalIgnoreCase))
            {
                str = str.Substring("lightning:".Length);
            }
            var decoded = InternalBech32Encoder.Instance.DecodeData(str);
            var hrp     = decoded.HumanReadablePart.ToLowerInvariant();

            Prefix        = hrp;
            MinimumAmount = LightMoney.Zero;
            if (Prefix.Length == 0)
            {
                throw new FormatException("Invalid BOLT11: No prefix");
            }
            ulong amount           = 0;
            int   firstNumberIndex = -1;

            for (int i = 0; i < Prefix.Length; i++)
            {
                int digit = Array.IndexOf(digits, Prefix[i]);
                if (digit != -1)
                {
                    if (firstNumberIndex == -1)
                    {
                        firstNumberIndex = i;
                    }
                    amount *= 10;
                    amount += (uint)digit;
                }
                else if (firstNumberIndex != -1)
                {
                    break;
                }
            }

            if (firstNumberIndex != -1)
            {
                LightMoneyUnit unit = LightMoneyUnit.BTC;
                switch (Prefix[Prefix.Length - 1])
                {
                case 'm':
                    unit = LightMoneyUnit.MilliBTC;
                    break;

                case 'u':
                    unit = LightMoneyUnit.Micro;
                    break;

                case 'n':
                    unit = LightMoneyUnit.Nano;
                    break;

                case 'p':
                    unit = LightMoneyUnit.Pico;
                    break;

                default:
                    if (Array.IndexOf(digits, Prefix[Prefix.Length - 1]) == -1)
                    {
                        throw new FormatException("Invalid BOLT11: invalid amount multiplier");
                    }
                    unit = LightMoneyUnit.BTC;
                    break;
                }
                MinimumAmount = LightMoney.FromUnit(amount, unit);
                Prefix        = Prefix.Substring(0, firstNumberIndex);
                if (Prefix.Length == 0)
                {
                    throw new FormatException("Invalid BOLT11: No prefix");
                }
            }

            if (_Prefixes.TryGetValue((network.NetworkSet.CryptoCode, network.NetworkType), out var expectedPrefix) &&
                expectedPrefix != Prefix)
            {
                throw new FormatException("Invalid BOLT11: Invalid prefix");
            }

            var bitArray = new BitArray(decoded.Data.Length * 5);

            for (int di = 0; di < decoded.Data.Length; di++)
            {
                bitArray.Set(di * 5 + 0, ((decoded.Data[di] >> 4) & 0x01) == 1);
                bitArray.Set(di * 5 + 1, ((decoded.Data[di] >> 3) & 0x01) == 1);
                bitArray.Set(di * 5 + 2, ((decoded.Data[di] >> 2) & 0x01) == 1);
                bitArray.Set(di * 5 + 3, ((decoded.Data[di] >> 1) & 0x01) == 1);
                bitArray.Set(di * 5 + 4, ((decoded.Data[di] >> 0) & 0x01) == 1);
            }

            var reader = new BitReader(bitArray);

            reader.Position = reader.Count - 520 - 30;
            if (reader.Position < 0)
            {
                throw new FormatException("Invalid BOLT11: Invalid size");
            }

            if (!reader.CanConsume(65))
            {
                throw new FormatException("Invalid BOLT11: Invalid size");
            }
            var rs = reader.ReadBytes(65);

            _OriginalFormat = rs;
            ECDSASignature  = new ECDSASignature(
                new NBitcoin.BouncyCastle.Math.BigInteger(1, rs, 0, 32),
                new NBitcoin.BouncyCastle.Math.BigInteger(1, rs, 32, 32));
            RecoveryId = rs[rs.Length - 1];

            reader.Position = 0;
            Timestamp       = Utils.UnixTimeToDateTime(reader.ReadULongBE(35));

            void AssertSize(int c)
            {
                if (!reader.CanConsume(c))
                {
                    throw new FormatException("Invalid BOLT11: invalid size");
                }
            }

            ExpiryDate         = Timestamp + TimeSpan.FromHours(1);
            MinFinalCLTVExpiry = 9;
            var fallbackAddresses = new List <BitcoinAddress>();
            var routes            = new List <RouteInformation>();

            while (reader.Position != reader.Count - 520 - 30)
            {
                AssertSize(5 + 10);
                var tag  = reader.ReadULongBE(5);
                var size = (int)(reader.ReadULongBE(10) * 5);
                AssertSize(size);
                var afterReadPosition = reader.Position + size;
                switch (tag)
                {
                case 1:
                    if (size != 52 * 5)
                    {
                        break;
                    }
                    if (PaymentHash != null)
                    {
                        throw new FormatException("Invalid BOLT11: Duplicate 'p'");
                    }
                    PaymentHash = new uint256(reader.ReadBytes(32), false);
                    break;

                case 6:
                    ExpiryDate = Timestamp + TimeSpan.FromSeconds(reader.ReadULongBE(size));
                    break;

                case 13:
                    var bytesCount = size / 8;
                    var bytes      = reader.ReadBytes(bytesCount);
                    try
                    {
                        ShortDescription = UTF8NoBOM.GetString(bytes, 0, bytesCount);
                    }
                    catch
                    {
                    }
                    break;

                case 19:
                    if (size != 53 * 5)
                    {
                        break;
                    }
                    ExplicitPayeePubKey = new PubKey(reader.ReadBytes(33));
                    break;

                case 24:
                    var value = reader.ReadULongBE(size);
                    if (value > int.MaxValue)
                    {
                        break;
                    }
                    MinFinalCLTVExpiry = (int)value;
                    break;

                case 9:
                    if (size < 5)
                    {
                        break;
                    }
                    var version = reader.ReadULongBE(5);
                    switch (version)
                    {
                    case 0:
                        if (size == 5 + (20 * 8))
                        {
                            fallbackAddresses.Add(new BitcoinWitPubKeyAddress(new WitKeyId(reader.ReadBytes(20)), network));
                        }
                        else if (size == 5 + (32 * 8) + 4)
                        {
                            fallbackAddresses.Add(new BitcoinWitScriptAddress(new WitScriptId(reader.ReadBytes(32)), network));
                        }
                        break;

                    case 17:
                        if (size != 5 + (20 * 8))
                        {
                            break;
                        }
                        fallbackAddresses.Add(new BitcoinPubKeyAddress(new KeyId(reader.ReadBytes(20)), network));
                        break;

                    case 18:
                        if (size != 5 + (20 * 8))
                        {
                            break;
                        }
                        fallbackAddresses.Add(new BitcoinScriptAddress(new ScriptId(reader.ReadBytes(20)), network));
                        break;

                    default:
                        break;
                    }
                    break;

                case 23:
                    if (size != 52 * 5)
                    {
                        break;
                    }
                    DescriptionHash = new uint256(reader.ReadBytes(32), true);
                    break;

                case 3:
                    if (size < 264 + 64 + 32 + 32 + 16)
                    {
                        break;
                    }
                    var positionBefore   = reader.Position;
                    var routeInformation = new RouteInformation(reader, size);
                    var readen           = reader.Position - positionBefore;
                    if (size - readen >= 5)
                    {
                        break;
                    }
                    routes.Add(routeInformation);
                    break;
                }
                var skip = afterReadPosition - reader.Position;
                if (skip < 0)
                {
                    throw new FormatException("Invalid BOLT11: Invalid size");
                }
                reader.Consume(skip);
            }

            reader = new BitReader(bitArray, bitArray.Count - 520 - 30);
            int byteCount = Math.DivRem(reader.Count, 8, out var remainder);

            if (remainder != 0)
            {
                byteCount++;
            }
            var hashedData = UTF8NoBOM.GetBytes(hrp).Concat(reader.ReadBytes(byteCount)).ToArray();

            Hash              = new uint256(Hashes.SHA256(hashedData));
            Routes            = routes;
            FallbackAddresses = fallbackAddresses;
        }
Ejemplo n.º 3
0
 public bool Run()
 {
     XmlRpc.XmlRpcRequest req = XmlRpc.DeserializeRequest(new MemoryStream(UTF8NoBOM.GetBytes(ParserInput)));
     return(true);
 }