public void CanCreateFunding() { var offer = Parse <Messages.Offer>("Data/Offer2.json"); var accept = Parse <Messages.Accept>("Data/Accept2.json"); var b = new DLCTransactionBuilder(true, offer, accept, null, Network.RegTest); var expected = Transaction.Parse("0200000000010213a31be98d8e29a08cbb3b64de59727b0a6285e2f34338a3ca576ae5250692fc0100000000ffffffffff9208b14cf747f04a7b653debb4dfedc9b4a3291985b91c872dda54b420e7110200000000ffffffff037418f605000000002200205f4c70ba1400d2efc70a2ff32f07a2d79c26d9f6c49a65bde68efc53cf12f0d5dcfb0d700000000016001486039150dbcfd4a136243a7cb4ea2b3dad24e606bbbfd17400000000160014775277f3b5fc4c32bed192ac6b3fd90b4403f1c902483045022100a9518901afbe84053644c0f08e50d45eb373616f7aa729677ecf5718f2fac8b2022032949f92beaf8d4ee8b944fa9452f1feabbc863e59b943fd5acce1aedc89feef012102a3795336df054e4fe408e0d453ff48fc8a0ec4ba7ef9234391babfa4247aef0a024730440220320baf857ca4ff420613e89930dcaa6ee423251fdcfc2108c7a029263cab5c2302201237c4b978c65ed3ed00bb763ff1d1b6f61bdaff8a29e5ca537761e089ce5265012103af3fb0e5788dbfdc478dd5e58d27001177a9a3fb19b990c883dd3ea75aec424c00000000", Network.Main); foreach (var input in expected.Inputs) { input.WitScript = WitScript.Empty; } // We cheat for now... b.FundingOverride = expected; var actual = b.BuildFunding(); Assert.Equal(expected.ToString(), actual.ToString()); expected = Transaction.Parse("02000000000101ef43cda2f4e8fb1e254864a00b3b81f4915b9c8d060e41fe37523001ac03a08a0000000000feffffff0200879303000000001600145e8bf52af230ae61e9637ecb498a5bed8d09a59b005a62020000000016001411eb59e70fa4abe8c02699b54fb71ed3d76574fc04004830450221009942f177f872e786f6d1edd98abc78e4114bcbd886a72170190e39515841da85022001908f53671480bd2eb869dc7c34d188921a72243dce1e3108646f83948e516401483045022100e988416aba7518317c7a3e1acf051e0ef28ba7cb0473039115072a4073a2a650022028ee55f5d202f9facc230aa7f7c9fd18a75228fc80493bea9d1ae36085cec8830147522103fbae911c3acb17f06a9a544f068d925715900c69d0c58408543c09e75ba249332103f81ee1a50b2b01ce32982b2900c34f0c3a3745e98458e67ecf239086f4e8908852aec8000000", Network.Main); foreach (var input in expected.Inputs) { input.WitScript = WitScript.Empty; } actual = b.BuildRefund(); Assert.Equal(expected.ToString(), actual.ToString()); }
public async Task dlc_test() { await foreach (var vector in DLCTestVector.ReadVectors()) { Assert.Equal(vector.ExpectedOfferTLV, Encoders.Hex.EncodeData(vector.Offer.ToTLV())); var accept = new Accept(); accept.TemporaryContractId = vector.Offer.GetTemporaryContractId(); vector.FillFundingInformation(accept, "acceptParams"); accept.PubKeys.FundingKey = vector.AcceptPrivateKey.PubKey; var acceptor = new DLCTransactionBuilder(false, null, null, null, Network.RegTest); acceptor.Accept(vector.Offer, accept.TotalCollateral); Assert.True(acceptor.State.TemporaryContractId); var builtAccept = acceptor.FundAccept(vector.AcceptPrivateKey, accept.CreateSetupPSBT(Network.RegTest)); accept.CetSigs = builtAccept.CetSigs; // this signature is non deterministic... accept.CetSigs.RefundSig = Accept.ParseFromTLV(vector.ExpectedAcceptTLV, Network.RegTest).CetSigs.RefundSig; Assert.Equal(vector.ExpectedAcceptTLV, Encoders.Hex.EncodeData(accept.ToTLV())); var actualFundingTransaction = acceptor.GetFundingTransaction(); var actualRefundTransaction = acceptor.BuildRefund(); var actualCETs = new Transaction[vector.Offer.ContractInfo.Length]; for (int i = 0; i < vector.Offer.ContractInfo.Length; i++) { actualCETs[i] = acceptor.BuildCET(vector.Offer.ContractInfo[i].Outcome); } var offerer = new DLCTransactionBuilder(true, vector.Offer, null, null, Network.RegTest); offerer.Sign1(accept); var fundingPSBT = offerer.GetFundingPSBT(); FillSignatures(fundingPSBT, vector.SignedTxs.FundingTx); var sign = offerer.Sign2(vector.OfferPrivateKey, fundingPSBT); // this signature is non deterministic... sign.CetSigs.RefundSig = Sign.ParseFromTLV(vector.ExpectedSignTLV, Network.RegTest).CetSigs.RefundSig; Assert.Equal(vector.ExpectedSignTLV, Encoders.Hex.EncodeData(sign.ToTLV())); Assert.Equal( RemoveForDebug(vector.UnsignedTxs.FundingTx.ToString()), RemoveForDebug(actualFundingTransaction.ToString())); Assert.Equal( RemoveForDebug(vector.UnsignedTxs.RefundTx.ToString()), RemoveForDebug(actualRefundTransaction.ToString())); for (int i = 0; i < actualCETs.Length; i++) { Assert.Equal( RemoveForDebug(vector.UnsignedTxs.Cets[i].ToString()), RemoveForDebug(actualCETs[i].ToString())); } Assert.NotNull(offerer.State.ContractId); Assert.Equal(offerer.State.ContractId, acceptor.State.ContractId); Assert.False(offerer.State.TemporaryContractId); } }
protected override async Task InvokeAsyncBase(InvocationContext context) { var name = context.ParseResult.CommandResult.GetArgumentValueOrDefault <string>("name")?.Trim(); if (name is null) { throw new CommandOptionRequiredException("name"); } var dlc = await GetDLC("name", name); if (dlc?.BuilderState is null || dlc?.OracleInfo is null) { throw new CommandException("name", "This DLC does not exist"); } var oracle = await Repository.GetOracle(dlc.OracleInfo.PubKey); string?oracleName = null; EventFullName eventName = new EventFullName("???", "???"); if (oracle != null) { oracleName = await NameRepository.GetName(Scopes.Oracles, new OracleId(dlc.OracleInfo.PubKey).ToString()); var ev = await Repository.GetEvent(dlc.OracleInfo); eventName = await NameRepository.AsEventRepository().ResolveName(dlc.OracleInfo) ?? eventName; } var shown = ParseShownItem(context); if (shown == ShowOption.DLC) { context.Console.Out.WriteLine($"Name: {name}"); context.Console.Out.WriteLine($"Local Id: {dlc.Id}"); var builder = new DLCTransactionBuilder(dlc.BuilderState.ToString(), Network); var role = builder.State.IsInitiator ? "Offerer" : "Acceptor"; context.Console.Out.WriteLine($"Event: {eventName}"); context.Console.Out.WriteLine($"Role: {role}"); var nextStep = dlc.GetNextStep(Network); context.Console.Out.WriteLine($"Next step: {nextStep}"); context.Console.Out.WriteLine($"Next step explanation:"); context.Console.Out.Write($"{Explain(nextStep, name, builder.State)}"); } else if (shown == ShowOption.Offer) { if (dlc.Offer is null) { throw new CommandException("offer", "No offer available for this DLC"); } context.WriteObject(dlc.Offer, Repository.JsonSettings); } else if (shown == ShowOption.Accept) { if (dlc.Accept is null) { throw new CommandException("offer", "No accept message available for this DLC"); } context.WriteObject(dlc.Accept, Repository.JsonSettings); } else if (shown == ShowOption.Funding) { try { var builder = new DLCTransactionBuilder(dlc.BuilderState.ToString(), Network); context.WritePSBT(builder.GetFundingPSBT()); } catch { throw new CommandException("funding", "No funding PSBT ready for this DLC"); } } else if (shown == ShowOption.Abort) { if (dlc.Abort is null) { throw new CommandException("abort", "No abort PSBT for this DLC"); } context.WritePSBT(dlc.Abort); } else if (shown == ShowOption.Refund) { try { var builder = new DLCTransactionBuilder(dlc.BuilderState.ToString(), Network); context.WriteTransaction(builder.BuildRefund(), Network); } catch { throw new CommandException("refund", "No refund PSBT ready for this DLC"); } } else { throw new NotSupportedException(); } }