private static bool TryCreate(ReadOnlySpan <byte> input64, [MaybeNullWhen(false)] out OracleInfo oracleInfo) { oracleInfo = null; if (input64.Length != 64) { return(false); } if (!ECXOnlyPubKey.TryCreate(input64.Slice(0, 32), Context.Instance, out var pubkey) || pubkey is null) { return(false); } if (!SchnorrNonce.TryCreate(input64.Slice(32), out var rValue) || rValue is null) { return(false); } oracleInfo = new OracleInfo(pubkey, rValue); return(true); }
public Offer Offer(PSBTFundingTemplate fundingTemplate, OracleInfo oracleInfo, ContractInfo[] contractInfo, Timeouts timeouts) { if (!isInitiator) { throw new InvalidOperationException("The acceptor can't initiate an offer"); } var fundingKey = this.FundingKey ?? new Key(); Offer offer = new Offer() { OracleInfo = oracleInfo, ContractInfo = contractInfo, Timeouts = timeouts }; offer.FillFromTemplateFunding(fundingTemplate, fundingKey.PubKey); this.FundingKey = fundingKey; this.OracleInfo = oracleInfo; FillStateFrom(offer); return(offer); }
public static bool TryParse(string str, out OracleInfo?oracleInfo) { oracleInfo = null; if (str == null) { throw new ArgumentNullException(nameof(str)); } var bytes = Encoders.Hex.DecodeData(str); if (bytes.Length != 64) { return(false); } if (!ECXOnlyPubKey.TryCreate(bytes.AsSpan().Slice(0, 32), Context.Instance, out var pubkey) || pubkey is null) { return(false); } if (!SchnorrNonce.TryCreate(bytes.AsSpan().Slice(32), out var rValue) || rValue is null) { return(false); } oracleInfo = new OracleInfo(pubkey, rValue); return(true); }
public void WriteTLV(TLVWriter writer) { if (ChainHash is null) { throw new InvalidOperationException($"{nameof(ChainHash)} is not set"); } if (ContractInfo is null) { throw new InvalidOperationException($"{nameof(ContractInfo)} is not set"); } if (OracleInfo is null) { throw new InvalidOperationException($"{nameof(OracleInfo)} is not set"); } if (TotalCollateral is null) { throw new InvalidOperationException($"{nameof(TotalCollateral)} is not set"); } if (PubKeys?.FundingKey is null) { throw new InvalidOperationException($"{nameof(PubKeys.FundingKey)} is not set"); } if (PubKeys?.PayoutAddress is null) { throw new InvalidOperationException($"{nameof(PubKeys.PayoutAddress)} is not set"); } if (FundingInputs is null) { throw new InvalidOperationException($"{nameof(FundingInputs)} is not set"); } if (ChangeAddress is null) { throw new InvalidOperationException($"{nameof(ChangeAddress)} is not set"); } if (FeeRate is null) { throw new InvalidOperationException($"{nameof(FeeRate)} is not set"); } if (Timeouts is null) { throw new InvalidOperationException($"{nameof(Timeouts)} is not set"); } writer.WriteU16(TLVType); writer.WriteByte(0); // contract_flags writer.WriteUInt256(ChainHash); using (var ciRecord = writer.StartWriteRecord(TLVContractInfoType)) { foreach (var ci in ContractInfo) { ciRecord.WriteBytes(ci.Outcome.Hash); ciRecord.WriteU64((ulong)ci.Payout.Satoshi); } } Span <byte> buf = stackalloc byte[64]; using (var oracleRecord = writer.StartWriteRecord(TLVOracleInfoType)) { OracleInfo.WriteToBytes(buf); oracleRecord.WriteBytes(buf); } PubKeys.FundingKey.Compress().ToBytes(buf, out _); writer.WriteBytes(buf.Slice(0, 33)); writer.WriteScript(PubKeys.PayoutAddress.ScriptPubKey); writer.WriteU64((ulong)TotalCollateral.Satoshi); writer.WriteU16((ushort)FundingInputs.Length); foreach (var input in FundingInputs) { input.WriteTLV(writer); } writer.WriteScript(ChangeAddress.ScriptPubKey); writer.WriteU64((ulong)FeeRate.SatoshiPerByte); writer.WriteU32((uint)Timeouts.ContractMaturity); writer.WriteU32((uint)Timeouts.ContractTimeout); }
public void ReadTLV(TLVReader reader, Network network) { if (reader.ReadU16() != TLVType) { throw new FormatException("Invalid TLV type for offer"); } reader.ReadByte(); // contract_flags ChainHash = reader.ReadUInt256(); if (network.GenesisHash != network.GenesisHash) { throw new FormatException("Invalid ChainHash"); } Span <byte> buf = stackalloc byte[64]; using (var ciRecord = reader.StartReadRecord()) { if (ciRecord.Type != TLVContractInfoType) { throw new FormatException("Invalid TLV type for contract info"); } List <ContractInfo> cis = new List <ContractInfo>(); while (!ciRecord.IsEnd) { ciRecord.ReadBytes(buf.Slice(0, 32)); var sats = ciRecord.ReadU64(); cis.Add(new Messages.ContractInfo(new DiscreteOutcome(buf.Slice(0, 32).ToArray()), Money.Satoshis(sats))); } ContractInfo = cis.ToArray(); } using (var oracleRecord = reader.StartReadRecord()) { if (oracleRecord.Type != TLVOracleInfoType) { throw new FormatException("Invalid TLV type for oracle info"); } oracleRecord.ReadBytes(buf.Slice(0, 64)); OracleInfo = OracleInfo.Create(buf); } PubKeys = new PubKeyObject(); reader.ReadBytes(buf.Slice(0, 33)); PubKeys.FundingKey = new PubKey(buf.Slice(0, 33).ToArray()); PubKeys.PayoutAddress = reader.ReadScript().GetDestinationAddress(network); if (PubKeys.PayoutAddress is null) { throw new FormatException("Invalid script"); } TotalCollateral = Money.Satoshis(reader.ReadU64()); var fiCount = reader.ReadU16(); List <FundingInput> fis = new List <FundingInput>(); while (fiCount > 0) { fis.Add(FundingInput.ParseFromTLV(reader, network)); fiCount--; } FundingInputs = fis.ToArray(); ChangeAddress = reader.ReadScript().GetDestinationAddress(network); if (ChangeAddress is null) { throw new FormatException("Invalid script"); } FeeRate = new FeeRate(Money.Satoshis(reader.ReadU64()), 1); Timeouts = new Timeouts() { ContractMaturity = reader.ReadU32(), ContractTimeout = reader.ReadU32() }; }