コード例 #1
0
        /// <summary>
        /// Fix case mistakes
        /// </summary>
        private static void FixCasing(Event evt, DiscretePayoffs payoffs)
        {
            HashSet <DiscreteOutcome> outcomes = new HashSet <DiscreteOutcome>();

            for (int i = 0; i < payoffs.Count; i++)
            {
                var outcomeString = payoffs[i].Outcome.OutcomeString?.Trim();
                if (outcomeString is null)
                {
                    throw new CommandException("payoff", "The payoff can't be parsed");
                }
                var knownOutcome = evt.Outcomes.Select(o => new DiscreteOutcome(o))
                                   .FirstOrDefault(o => o.OutcomeString !.Equals(outcomeString, StringComparison.OrdinalIgnoreCase));
                if (knownOutcome is null)
                {
                    throw new CommandException("payoff", $"This outcome {outcomeString} is not part of the event");
                }
                outcomes.Add(knownOutcome);
                payoffs[i] = new DiscretePayoff(knownOutcome, payoffs[i].Reward);
            }

            if (outcomes.Count != evt.Outcomes.Length)
            {
                throw new CommandException("payoff", $"You did not specified the reward of all outcomes of the event");
            }
        }
コード例 #2
0
        public Money Offer(
            ECXOnlyPubKey oraclePubKey,
            SchnorrNonce eventNonce,
            DiscretePayoffs offererPayoffs,
            Timeouts timeouts, Money?collateral = null)
        {
            using var tx = StartTransaction();
            if (!s.IsInitiator)
            {
                throw new InvalidOperationException("The acceptor can't initiate an offer");
            }
            s.OracleInfo     = new OracleInfo(oraclePubKey, eventNonce);
            s.Timeouts       = timeouts;
            s.OffererPayoffs = offererPayoffs;
            s.Offerer        = new Party();
            var minimumCollateral = offererPayoffs.CalculateMinimumCollateral();

            if (collateral is Money m && m < minimumCollateral)
            {
                throw new ArgumentException($"The collateral is too small, it should be at least {minimumCollateral.ToString(false, false)}");
            }
            s.Offerer.Collateral = collateral ?? minimumCollateral;
            tx.Commit();
            return(s.Offerer.Collateral);
        }
コード例 #3
0
        private DiscretePayoffs GetOutcomes(string[]?outcomes)
        {
            string optionName = "outcome";

            if (outcomes is null || outcomes.Length is 0)
            {
                throw new CommandOptionRequiredException(optionName);
            }
            DiscretePayoffs pnl = new DiscretePayoffs();

            for (int i = 0; i < outcomes.Length; i++)
            {
                var separator = outcomes[i].LastIndexOf(':');
                if (separator == -1)
                {
                    throw new CommandException(optionName, "Invalid outcome, the format should be \'outcome:reward\' where \'reward\' is in sats (\'1000 sats\') or in BTC (\'0.2\')");
                }
                var outcome = outcomes[i].Substring(0, separator);
                var reward  = outcomes[i].Substring(separator + 1);
                reward = reward.ToLowerInvariant().Trim();
                var   satsSeparator = reward.IndexOf("sats");
                Money rewardMoney   = Money.Zero;
                if (satsSeparator == -1)
                {
                    rewardMoney = Money.Parse(reward);
                }
                else
                {
                    rewardMoney = Money.Satoshis(long.Parse(reward.Substring(0, satsSeparator)));
                }
                pnl.Add(new DiscretePayoff(outcome, rewardMoney));
            }
            return(pnl);
        }
コード例 #4
0
        public void FillStateFrom(Offer?offer)
        {
            if (offer is null)
            {
                return;
            }
            s.OffererInputs = offer.FundingInputs;
            s.OffererChange = offer.ChangeAddress?.ScriptPubKey;
            s.OracleInfo    = offer.OracleInfo;
            s.Timeouts      = offer.Timeouts;
            s.ContractId    = offer.GetTemporaryContractId();
            s.Offerer ??= new Party();

            if (offer.ContractInfo is ContractInfo[] c &&
                c.Length > 0 &&
                offer.TotalCollateral is Money)
            {
                s.OffererPayoffs = DiscretePayoffs.CreateFromContractInfo(offer.ContractInfo, offer.TotalCollateral);
            }
            s.Offerer.VSizes            = new VSizeCalculator(offer).Calculate();
            s.Offerer.Collateral        = offer.TotalCollateral ?? s.OffererPayoffs?.CalculateMinimumCollateral();
            s.Offerer.FundPubKey        = offer.PubKeys?.FundingKey;
            s.Offerer.PayoutDestination = offer.PubKeys?.PayoutAddress?.ScriptPubKey;
            s.FeeRate = offer.FeeRate;
        }
コード例 #5
0
        public DiscretePayoffs ToDiscretePayoffs(ContractInfo[] contractInfo)
        {
            if (contractInfo is null || contractInfo.Length is 0)
            {
                throw new ArgumentException("contractInfo is required", nameof(contractInfo));
            }
            DiscretePayoffs payoffs = new DiscretePayoffs();

            foreach (var ci in contractInfo)
            {
                payoffs.Add(new DiscretePayoff(ci.Outcome, ci.Payout - TotalCollateral));
            }
            return(payoffs);
        }
コード例 #6
0
        private DiscretePayoffs CreatePayoffs(List <string> payoffs)
        {
            var result = new DiscretePayoffs();

            foreach (var payoff in payoffs)
            {
                if (!DiscretePayoff.TryParse(payoff, out var o) || o is null)
                {
                    throw new CommandException("payoff", "The payoff can't be parsed");
                }
                result.Add(o);
            }
            return(result);
        }
コード例 #7
0
ファイル: BitcoinSTests.cs プロジェクト: dgarage/NDLC
        public void CanConvertContractInfoToPayoff()
        {
            var payoffs = new DiscretePayoffs();

            payoffs.Add(new DiscreteOutcome("a"), Money.Coins(5.0m));
            payoffs.Add(new DiscreteOutcome("b"), Money.Coins(-5.0m));
            payoffs.Add(new DiscreteOutcome("c"), Money.Coins(-2.0m));
            Assert.Equal(Money.Coins(5.0m), payoffs.CalculateMinimumCollateral());
            var ci = payoffs.ToContractInfo(payoffs.CalculateMinimumCollateral());

            Assert.Equal(Money.Coins(10.0m), ci[0].Payout);
            Assert.Equal(Money.Coins(0m), ci[1].Payout);
            Assert.Equal(Money.Coins(3.0m), ci[2].Payout);

            payoffs = DiscretePayoffs.CreateFromContractInfo(ci, Money.Coins(5.0m));
            Assert.Equal(Money.Coins(5.0m), payoffs[0].Reward);
            Assert.Equal(Money.Coins(-5.0m), payoffs[1].Reward);
            Assert.Equal(Money.Coins(-2.0m), payoffs[2].Reward);
        }
コード例 #8
0
ファイル: BitcoinSTests.cs プロジェクト: theotherside/NDLC
        public void FullExchange()
        {
            var offerExample      = Parse <Messages.Offer>("Data/Offer2.json");
            var offerKey          = new Key();
            var acceptKey         = new Key();
            var initiatorInputKey = new Key();
            var acceptorInputKey  = new Key();
            var initiator         = new DLCTransactionBuilder(true, null, null, null, Network.RegTest);
            var requiredFund      = initiator.Offer(offerExample.OracleInfo.PubKey,
                                                    offerExample.OracleInfo.RValue,
                                                    DiscretePayoffs.CreateFromContractInfo(offerExample.ContractInfo, offerExample.TotalCollateral,
                                                                                           new[] { new DiscreteOutcome("Republicans_win"), new DiscreteOutcome("Democrats_win"), new DiscreteOutcome("other") }),
                                                    offerExample.Timeouts);
            var fund1          = GetFundingPSBT(initiatorInputKey, requiredFund);
            var offer          = initiator.FundOffer(offerKey, fund1);
            var acceptor       = new DLCTransactionBuilder(false, null, null, null, Network.RegTest);
            var acceptorPayoff = acceptor.Accept(offer);
            var fund2          = GetFundingPSBT(acceptorInputKey, acceptorPayoff.CalculateMinimumCollateral());
            var accept         = acceptor.FundAccept(acceptKey, fund2);

            initiator.Sign1(accept);
            var fundPSBT = initiator.GetFundingPSBT();

            fundPSBT.SignWithKeys(initiatorInputKey);
            var sign = initiator.Sign2(offerKey, fundPSBT);

            acceptor.Finalize1(sign);
            fundPSBT = acceptor.GetFundingPSBT();
            fundPSBT.SignWithKeys(acceptorInputKey);
            var fullyVerified = acceptor.Finalize(fundPSBT);

            foreach (var i in fullyVerified.Inputs)
            {
                Assert.NotNull(i.WitScript);
            }
            fundPSBT = acceptor.GetFundingPSBT();
            if (fundPSBT.TryGetEstimatedFeeRate(out var estimated))
            {
                Assert.True(estimated > new FeeRate(1.0m), "Fee Rate of the funding PSBT are too low");
            }
        }