diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 6a026a2fa..7607b4961 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -10,6 +10,7 @@ | Ilja von Hoessle | [@iljabvh](https://github.com/iljabvh) | iljabvh | | Jens Winkle | [@DragonDev1906](https://github.com/DragonDev1906) | jens#4601 | | Minh Huy Tran | [@NhoxxKienn](https://github.com/NhoxxKienn) | NhoxxKienn | +| Sophia Koehler | [@sophia1ch](https://githun.com/sophia1ch) | sophia#3072 | ## Emeritus Maintainers diff --git a/NOTICE b/NOTICE index 5154d5d50..7b42b10f0 100644 --- a/NOTICE +++ b/NOTICE @@ -44,6 +44,7 @@ PolyCrypt GmbH Ilja von Hoessle Jens Winkle Minh Huy Tran + Sophia Koehler Robert Bosch GmbH Manoranjith diff --git a/channel/adjudicator.go b/channel/adjudicator.go index 1751a5469..ddfd1a7b0 100644 --- a/channel/adjudicator.go +++ b/channel/adjudicator.go @@ -103,11 +103,17 @@ type ( // An AdjudicatorReq collects all necessary information to make calls to the // adjudicator. + // + // If the Secondary flag is set to true, it is assumed that this is an + // on-chain request that is executed by the other channel participants as well + // and the Adjudicator backend may run an optimized on-chain transaction + // protocol, possibly saving unnecessary double sending of transactions. AdjudicatorReq struct { - Params *Params - Acc wallet.Account - Tx Transaction - Idx Index // Always the own index + Params *Params + Acc wallet.Account + Tx Transaction + Idx Index // Always the own index + Secondary bool // Optimized secondary call protocol } // SignedState represents a signed channel state including parameters. diff --git a/channel/machine.go b/channel/machine.go index 7d836b2a5..0175a2067 100644 --- a/channel/machine.go +++ b/channel/machine.go @@ -249,6 +249,9 @@ func (m *machine) CurrentTX() Transaction { // AdjudicatorReq returns the adjudicator request for the current channel // transaction (the current state together with all participants' signatures on // it). +// +// The Secondary flag is left as false. Set it manually after creating the +// request if you want to use optimized sencondary adjudication logic. func (m *machine) AdjudicatorReq() AdjudicatorReq { return AdjudicatorReq{ Params: &m.params, @@ -335,8 +338,9 @@ func (m *machine) EnableFinal() error { } // enableStaged checks that -// 1. the current phase is `expected.From` and -// 2. all signatures of the staging transactions have been set. +// 1. the current phase is `expected.From` and +// 2. all signatures of the staging transactions have been set. +// // If successful, the staging transaction is promoted to be the current // transaction. If not, an error is returned. func (m *machine) enableStaged(expected PhaseTransition) error { diff --git a/client/adjudicate.go b/client/adjudicate.go index 31cff0431..7cdd616f2 100644 --- a/client/adjudicate.go +++ b/client/adjudicate.go @@ -242,7 +242,7 @@ func (c *Channel) ForceUpdate(ctx context.Context, updater func(*channel.State)) // to be mined. // Returns ChainNotReachableError if the connection to the blockchain network // fails when sending a transaction to / reading from the blockchain. -func (c *Channel) Settle(ctx context.Context) (err error) { +func (c *Channel) Settle(ctx context.Context, secondary bool) (err error) { if !c.State().IsFinal { err := c.ensureRegistered(ctx) if err != nil { @@ -268,7 +268,7 @@ func (c *Channel) Settle(ctx context.Context) (err error) { } // Withdraw. - err = c.withdraw(ctx) + err = c.withdraw(ctx, secondary) if err != nil { return } @@ -303,7 +303,7 @@ func (c *Channel) Settle(ctx context.Context) (err error) { return nil } -func (c *Channel) withdraw(ctx context.Context) error { +func (c *Channel) withdraw(ctx context.Context, secondary bool) error { switch { case c.IsLedgerChannel(): subStates, err := c.subChannelStateMap() @@ -311,6 +311,7 @@ func (c *Channel) withdraw(ctx context.Context) error { return errors.WithMessage(err, "creating sub-channel state map") } req := c.machine.AdjudicatorReq() + req.Secondary = secondary if err := c.adjudicator.Withdraw(ctx, req, subStates); err != nil { return errors.WithMessage(err, "calling Withdraw") } diff --git a/client/test/bob.go b/client/test/bob.go index b554cde8b..de215f6bf 100644 --- a/client/test/bob.go +++ b/client/test/bob.go @@ -57,7 +57,7 @@ func (r *Bob) exec(_cfg ExecConfig, ch *paymentChannel, propHandler *acceptNextP ch.sendFinal() // 4th Settle channel - ch.settle() + ch.settleSecondary() // 4th final stage r.waitStage() diff --git a/client/test/channel.go b/client/test/channel.go index a0b0187a4..ff023626b 100644 --- a/client/test/channel.go +++ b/client/test/channel.go @@ -168,10 +168,18 @@ func (ch *paymentChannel) recvFinal() { } func (ch *paymentChannel) settle() { + ch.settleImpl(false) +} + +func (ch *paymentChannel) settleSecondary() { + ch.settleImpl(true) +} + +func (ch *paymentChannel) settleImpl(secondary bool) { ctx, cancel := context.WithTimeout(context.Background(), ch.r.timeout) defer cancel() - ch.r.RequireNoError(ch.Settle(ctx)) + ch.r.RequireNoError(ch.Settle(ctx, secondary)) ch.assertBals(ch.State()) if ch.IsSubChannel() { diff --git a/client/test/fund.go b/client/test/fund.go index 355553efd..76a15900d 100644 --- a/client/test/fund.go +++ b/client/test/fund.go @@ -129,7 +129,7 @@ func runFredFridaTest( require.IsType(t, &client.ChannelFundingError{}, err) require.NotNil(t, chFrida) // Frida settles the channel. - require.NoError(t, chFrida.Settle(ctx)) + require.NoError(t, chFrida.Settle(ctx, false)) // Fred gets the channel and settles it afterwards. chFred := <-chsFred @@ -141,7 +141,7 @@ func runFredFridaTest( require.NoError(t, ctx.Err()) } // Fred settles the channel. - require.NoError(t, chFred.Settle(ctx)) + require.NoError(t, chFred.Settle(ctx, false)) // Test the final balances. balancesAfter := channel.Balances{ diff --git a/client/test/multiledger_dispute.go b/client/test/multiledger_dispute.go index 0d6febc3b..b153f4435 100644 --- a/client/test/multiledger_dispute.go +++ b/client/test/multiledger_dispute.go @@ -31,6 +31,7 @@ import ( // TestMultiLedgerDispute runs an end-to-end test of the multi-ledger // functionality in the dispute case for the implementation specified in the // test setup. +// //nolint:revive // test.Test... stutters but this is OK in this special case. func TestMultiLedgerDispute( ctx context.Context, @@ -127,9 +128,9 @@ func TestMultiLedgerDispute( require.NoError(err) // Settle. - err = chAliceBob.Settle(ctx) + err = chAliceBob.Settle(ctx, false) require.NoError(err) - err = chBobAlice.Settle(ctx) + err = chBobAlice.Settle(ctx, false) require.NoError(err) // Close the channels. diff --git a/client/test/multiledger_happy.go b/client/test/multiledger_happy.go index f8958c63b..9ec8c021b 100644 --- a/client/test/multiledger_happy.go +++ b/client/test/multiledger_happy.go @@ -27,6 +27,7 @@ import ( // TestMultiLedgerHappy runs an end-to-end test of the multi-ledger // functionality in the optimistic case for the implementation specified in the // test setup. +// //nolint:revive // test.Test... stutters but this is OK in this special case. func TestMultiLedgerHappy(ctx context.Context, t *testing.T, mlt MultiLedgerSetup, challengeDuration uint64) { require := require.New(t) @@ -90,8 +91,8 @@ func TestMultiLedgerHappy(ctx context.Context, t *testing.T, mlt MultiLedgerSetu require.NoError(err) // Close channel. - err = chAliceBob.Settle(ctx) + err = chAliceBob.Settle(ctx, false) require.NoError(err) - err = chBobAlice.Settle(ctx) + err = chBobAlice.Settle(ctx, false) require.NoError(err) } diff --git a/client/test/persistence.go b/client/test/persistence.go index 726119e8d..d44a12fda 100644 --- a/client/test/persistence.go +++ b/client/test/persistence.go @@ -125,7 +125,7 @@ func (r *Petra) Execute(cfg ExecConfig) { // 6. Finalize restored channel ch.recvFinal() - ch.settle() + ch.settleSecondary() r.RequireNoError(r.Close()) } diff --git a/client/test/progression.go b/client/test/progression.go index 33c399b1e..be498dd9c 100644 --- a/client/test/progression.go +++ b/client/test/progression.go @@ -116,7 +116,7 @@ func (r *Paul) exec(_cfg ExecConfig, ch *paymentChannel) { r.waitStage() // withdraw - r.RequireNoError(ch.Settle(ctx)) + r.RequireNoError(ch.Settle(ctx, false)) } // ----------------- BEGIN PAULA ----------------- @@ -181,5 +181,5 @@ func (r *Paula) exec(_cfg ExecConfig, ch *paymentChannel, _ *acceptNextPropHandl r.RequireNoErrorf(e.Timeout().Wait(ctx), "waiting for progression timeout") // withdraw - r.RequireNoError(ch.Settle(ctx)) + r.RequireNoError(ch.Settle(ctx, true)) } diff --git a/client/test/subchannel.go b/client/test/subchannel.go index 247c39394..3480751d5 100644 --- a/client/test/subchannel.go +++ b/client/test/subchannel.go @@ -209,7 +209,7 @@ func (r *Tim) exec(_cfg ExecConfig, ledgerChannel *paymentChannel, propHandler * finalizeAndSettle := func(ch *paymentChannel) { ch.recvFinal() - ch.settle() + ch.settleSecondary() } for i, ch := range subChannels { diff --git a/client/test/virtualchannel.go b/client/test/virtualchannel.go index 31ceec45b..5d1449160 100644 --- a/client/test/virtualchannel.go +++ b/client/test/virtualchannel.go @@ -56,7 +56,7 @@ func TestVirtualChannelOptimistic( //nolint:revive // test.Test... stutters but success.Add(len(chs)) for _, ch := range chs { go func(ch *client.Channel) { - err := ch.Settle(ctx) + err := ch.Settle(ctx, false) if err != nil { vct.errs <- err return @@ -102,7 +102,7 @@ func TestVirtualChannelDispute( //nolint:revive // test.Test... stutters but OK // Settle the channels in a random order. for _, i := range rand.Perm(len(chs)) { - err := chs[i].Settle(ctx) + err := chs[i].Settle(ctx, false) assert.NoErrorf(err, "settle channel: %d", i) } diff --git a/watcher/local/watcher.go b/watcher/local/watcher.go index 97dfdfb8d..b74de505f 100644 --- a/watcher/local/watcher.go +++ b/watcher/local/watcher.go @@ -439,8 +439,9 @@ func makeSignedState(params *channel.Params, tx channel.Transaction) channel.Sig func makeAdjudicatorReq(params *channel.Params, tx channel.Transaction) channel.AdjudicatorReq { return channel.AdjudicatorReq{ - Params: params, - Tx: tx, + Params: params, + Tx: tx, + Secondary: false, } }