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; }
public bool Run() { XmlRpc.XmlRpcRequest req = XmlRpc.DeserializeRequest(new MemoryStream(UTF8NoBOM.GetBytes(ParserInput))); return(true); }