Skip to content

Commit b53c36b

Browse files
authored
Feat multiple backends (#410)
* feat(wallet, channel): Change backend to map of backends feat(Asset, Adjudicator): Add AssetID struct to identify assets with LedgerID and BackendID feat(persistence, wire): Use map[int]Address to identify clients Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(multi): Add AssetIDKey struct to fix the map lookups for funders and adjudicators. fix(randomizer): Lookup backend opts to correctly initialize address maps. fix(test): Generalize tests to be used in other backends. Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(all): Use map[int]ID instead of id for each backend. Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(all): Add map of IDs Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(channel/backend): Revert change in verify. fix(wallet/wallet, wallet/account): Revert changed definition. feat(client): Add wallet map to client for each backend. Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(Adjudicator): Change to singular channel ID in events. Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(client/test): Generalize role test. Signed-off-by: Sophia Koehler <sophia@perun.network> * feat(channel): Add backend field check. feat(client/test, wire): Add backendID arguments. Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(subchannel_dispute): Generalize event watcher. Signed-off-by: Sophia Koehler <sophia@perun.network> * feat: Asset Address function to handle encoding in backends. Signed-off-by: Sophia Koehler <sophia@perun.network> * feat(apps/payment, backend/sim, channel/test, client/test, log, wallet, ): Specify backend for randomizers feat(channel/multi): Change AssetID to interface feat(channel/persistence, client/test): Generalize test for backends Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(asset.go, allocation.go): Adjust Address() to return byte[] instead of string. fix(params.go): Change IDKey to encode map entries sorted by keys. fix(backend.go): Use BackendID in argument to sign depending on backend. fix(address.go): Sort Addresses by keys before adding them to Keys. Signed-off-by: Sophia Koehler <sophia@perun.network> * chore: Remove unnecessary logs Signed-off-by: Sophia Koehler <sophia@perun.network> * fix: Remove repeated assetIDs in LedgerID array Signed-off-by: Sophia Koehler <sophia@perun.network> * chore: update go.sum, gofmt some files Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(wallet/backend.go): Return just one error instead of concatenation of errors chore(All): Run gofmt and sort imports Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(golangci.yml): Exclude generated file from linter chore: Refactor for linter Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(ci): Use go1.18 for the any type in proto fix(golangci): Fix structure Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(ci): Use glinter 1.45 which supports go1.18 Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): Add nolint flags for conversions Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): remove unnecessary flags Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): remove unnecessary flags Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): remove unnecessary flags Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): remove unnecessary flags Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): remove unnecessary flags Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): remove unnecessary flags Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): remove unnecessary flags Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): Rename and add comments to exported functions Signed-off-by: Sophia Koehler <sophia@perun.network> * chore: Rename variables Signed-off-by: Sophia Koehler <sophia@perun.network> * fix(params, address): Fix index allocation Signed-off-by: Sophia Koehler <sophia@perun.network> * refactor(/apps/payment, /sim/wallet, /channel, /client, /wallet, /wire): Name test backend ID in tests refactor(/multi, /client/test): Rename AssetID to MultiLedgerID Signed-off-by: Sophia Koehler <sophia@perun.network> * refactor: Name TestBackendID, rename multiLedgerID to LedgerBackendID Signed-off-by: Sophia Koehler <sophia@perun.network> * refactor: Fix comment on exported function Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(all): Update license dates Signed-off-by: Sophia Koehler <sophia@perun.network> * chore(backendtest): Rename to fix import issues Signed-off-by: Sophia Koehler <sophia@perun.network> * chore: Update license date fix: revert increased timeouts Signed-off-by: Sophia Koehler <sophia@perun.network> --------- Signed-off-by: Sophia Koehler <sophia@perun.network>
1 parent 381fe48 commit b53c36b

File tree

152 files changed

+3610
-1961
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+3610
-1961
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
release:
88

99
env:
10-
go-version: 1.17
10+
go-version: 1.18
1111

1212
jobs:
1313
check-copyright:
@@ -39,7 +39,7 @@ jobs:
3939
- name: golangci-lint
4040
uses: golangci/golangci-lint-action@v3
4141
with:
42-
version: v1.43
42+
version: v1.45
4343

4444
- name: Lint proto files
4545
uses: plexsystems/protolint-action@v0.6.0

.golangci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ linters-settings:
5454
# Default values:
5555
- ^print.*$
5656
- 'fmt\.Print.*'
57-
57+
exclude-rules:
58+
- path: ".*\\.pb\\.go$" # Exclude protobuf generated files.
5859
issues:
5960
# Re-enable default excludes.
6061
include:

apps/payment/app_internal_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ import (
2727

2828
func TestApp_Def(t *testing.T) {
2929
rng := pkgtest.Prng(t)
30-
def := test.NewRandomAppID(rng)
30+
def := test.NewRandomAppID(rng, channel.TestBackendID)
3131
app := &App{def}
3232
assert.True(t, app.Def().Equal(app.Def()))
3333
}

apps/payment/randomizer.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -17,6 +17,8 @@ package payment
1717
import (
1818
"math/rand"
1919

20+
"perun.network/go-perun/wallet"
21+
2022
"perun.network/go-perun/channel"
2123
"perun.network/go-perun/channel/test"
2224
)
@@ -27,8 +29,8 @@ type Randomizer struct{}
2729
var _ test.AppRandomizer = (*Randomizer)(nil)
2830

2931
// NewRandomApp always returns a payment app with a different address.
30-
func (*Randomizer) NewRandomApp(rng *rand.Rand) channel.App {
31-
return &App{test.NewRandomAppID(rng)}
32+
func (*Randomizer) NewRandomApp(rng *rand.Rand, bID wallet.BackendID) channel.App {
33+
return &App{test.NewRandomAppID(rng, bID)}
3234
}
3335

3436
// NewRandomData returns NoData because a PaymentApp does not have data.

apps/payment/randomizer_internal_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ func TestRandomizer(t *testing.T) {
2828
rng := pkgtest.Prng(t)
2929

3030
r := new(Randomizer)
31-
app := r.NewRandomApp(rng)
31+
app := r.NewRandomApp(rng, channel.TestBackendID)
3232
channel.RegisterApp(app)
3333
regApp, err := channel.Resolve(app.Def())
3434
assert.NoError(t, err)

apps/payment/resolver_internal_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@ func TestResolver(t *testing.T) {
3232
rng := pkgtest.Prng(t)
3333
assert, require := assert.New(t), require.New(t)
3434

35-
def := ctest.NewRandomAppID(rng)
35+
def := ctest.NewRandomAppID(rng, channel.TestBackendID)
3636
channel.RegisterAppResolver(def.Equal, &Resolver{})
3737

3838
app, err := channel.Resolve(def)

backend/sim/channel/app.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2022 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -48,5 +48,5 @@ func (id AppID) Key() channel.AppIDKey {
4848
// NewRandomAppID generates a new random app identifier.
4949
func NewRandomAppID(rng *rand.Rand) AppID {
5050
addr := wallet.NewRandomAddress(rng)
51-
return AppID{addr}
51+
return AppID{Address: addr}
5252
}

backend/sim/channel/asset.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -65,3 +65,9 @@ func (a Asset) Equal(b channel.Asset) bool {
6565
}
6666
return a.ID == simAsset.ID
6767
}
68+
69+
// Address returns the address of the asset.
70+
func (a Asset) Address() []byte {
71+
data, _ := a.MarshalBinary()
72+
return data
73+
}

backend/sim/channel/backend.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -33,23 +33,22 @@ type backend struct{}
3333
var _ channel.Backend = new(backend)
3434

3535
// CalcID calculates a channel's ID by hashing all fields of its parameters.
36-
func (*backend) CalcID(p *channel.Params) (id channel.ID) {
36+
func (*backend) CalcID(p *channel.Params) (id channel.ID, err error) {
3737
w := sha256.New()
3838

3939
// Write Parts
40-
for _, addr := range p.Parts {
41-
if err := perunio.Encode(w, addr); err != nil {
42-
log.Panic("Could not write to sha256 hasher")
43-
}
40+
if err := perunio.Encode(w, wallet.AddressMapArray{Addr: p.Parts}); err != nil {
41+
log.Panic("Could not write to sha256 hasher")
4442
}
4543

46-
err := perunio.Encode(w, p.Nonce, p.ChallengeDuration, channel.OptAppEnc{App: p.App}, p.LedgerChannel, p.VirtualChannel)
44+
err = perunio.Encode(w, p.Nonce, p.ChallengeDuration, channel.OptAppEnc{App: p.App}, p.LedgerChannel, p.VirtualChannel)
4745
if err != nil {
48-
log.Panic("Could not write to sha256 hasher")
46+
return
4947
}
5048

5149
if copy(id[:], w.Sum(nil)) != channel.IDLen {
52-
log.Panic("Could not copy id")
50+
err = errors.New("Could not copy id")
51+
return
5352
}
5453
return
5554
}
@@ -83,7 +82,7 @@ func (b *backend) NewAsset() channel.Asset {
8382

8483
// NewAppID returns an object of type AppID, which can be used for
8584
// unmarshalling an app identifier from its binary representation.
86-
func (b *backend) NewAppID() channel.AppID {
85+
func (b *backend) NewAppID() (channel.AppID, error) {
8786
addr := &simwallet.Address{}
88-
return AppID{addr}
87+
return AppID{addr}, nil
8988
}

backend/sim/channel/channel_internal_test.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -17,6 +17,8 @@ package channel
1717
import (
1818
"testing"
1919

20+
"perun.network/go-perun/channel"
21+
2022
chtest "perun.network/go-perun/channel/test"
2123
"perun.network/go-perun/wallet"
2224
wtest "perun.network/go-perun/wallet/test"
@@ -36,11 +38,13 @@ func newChannelSetup(t *testing.T) *chtest.Setup {
3638
params2, state2 := chtest.NewRandomParamsAndState(rng, chtest.WithIsFinal(!state.IsFinal), chtest.WithNumLocked(int(rng.Int31n(4)+1)))
3739

3840
return &chtest.Setup{
39-
Params: params,
40-
Params2: params2,
41-
State: state,
42-
State2: state2,
43-
Account: wtest.NewRandomAccount(rng),
44-
RandomAddress: func() wallet.Address { return wtest.NewRandomAddress(rng) },
41+
Params: params,
42+
Params2: params2,
43+
State: state,
44+
State2: state2,
45+
Account: wtest.NewRandomAccount(rng, channel.TestBackendID),
46+
RandomAddress: func() map[wallet.BackendID]wallet.Address {
47+
return wtest.NewRandomAddresses(rng, channel.TestBackendID)
48+
},
4549
}
4650
}

backend/sim/channel/init.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -22,9 +22,9 @@ import (
2222
)
2323

2424
func init() {
25-
channel.SetBackend(new(backend))
26-
test.SetRandomizer(new(randomizer))
25+
channel.SetBackend(new(backend), channel.TestBackendID)
26+
test.SetRandomizer(new(randomizer), channel.TestBackendID)
2727
test.SetNewRandomAppID(func(r *rand.Rand) channel.AppID {
2828
return NewRandomAppID(r)
29-
})
29+
}, channel.TestBackendID)
3030
}

backend/sim/wallet/account.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@ func NewRandomAccount(rng io.Reader) *Account {
5757

5858
// Address returns the address of this account.
5959
func (a *Account) Address() wallet.Address {
60-
return wallet.Address((*Address)(&a.privKey.PublicKey))
60+
return (*Address)(&a.privKey.PublicKey)
6161
}
6262

6363
// SignData is used to sign data with this account. If the account is locked,

backend/sim/wallet/address.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -20,13 +20,20 @@ import (
2020
"io"
2121
"math/big"
2222

23+
"perun.network/go-perun/channel"
24+
2325
"perun.network/go-perun/log"
2426
"perun.network/go-perun/wallet"
2527
)
2628

2729
// Address represents a simulated address.
2830
type Address ecdsa.PublicKey
2931

32+
// BackendID returns the backend id of the address.
33+
func (a Address) BackendID() wallet.BackendID {
34+
return channel.TestBackendID
35+
}
36+
3037
const (
3138
// elemLen is the length of the binary representation of a single element
3239
// of the address in bytes.
@@ -54,6 +61,21 @@ func NewRandomAddress(rng io.Reader) *Address {
5461
}
5562
}
5663

64+
// NewRandomAddresses creates a new address using the randomness
65+
// provided by rng.
66+
func NewRandomAddresses(rng io.Reader) map[int]wallet.Address {
67+
privateKey, err := ecdsa.GenerateKey(curve, rng)
68+
if err != nil {
69+
log.Panicf("Creation of account failed with error", err)
70+
}
71+
72+
return map[int]wallet.Address{channel.TestBackendID: &Address{
73+
Curve: privateKey.Curve,
74+
X: privateKey.X,
75+
Y: privateKey.Y,
76+
}}
77+
}
78+
5779
// Bytes converts this address to bytes.
5880
func (a *Address) Bytes() []byte {
5981
data := a.byteArray()
@@ -90,9 +112,11 @@ func (a *Address) Equal(addr wallet.Address) bool {
90112
}
91113

92114
// Cmp checks the ordering of two addresses according to following definition:
93-
// -1 if (a.X < addr.X) || ((a.X == addr.X) && (a.Y < addr.Y))
94-
// 0 if (a.X == addr.X) && (a.Y == addr.Y)
95-
// +1 if (a.X > addr.X) || ((a.X == addr.X) && (a.Y > addr.Y))
115+
//
116+
// -1 if (a.X < addr.X) || ((a.X == addr.X) && (a.Y < addr.Y))
117+
// 0 if (a.X == addr.X) && (a.Y == addr.Y)
118+
// +1 if (a.X > addr.X) || ((a.X == addr.X) && (a.Y > addr.Y))
119+
//
96120
// So the X coordinate is weighted higher.
97121
// Pancis if the passed address is of the wrong type.
98122
func (a *Address) Cmp(addr wallet.Address) int {

backend/sim/wallet/init.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -15,11 +15,12 @@
1515
package wallet
1616

1717
import (
18+
"perun.network/go-perun/channel"
1819
"perun.network/go-perun/wallet"
1920
"perun.network/go-perun/wallet/test"
2021
)
2122

2223
func init() {
23-
wallet.SetBackend(new(Backend))
24-
test.SetRandomizer(newRandomizer())
24+
wallet.SetBackend(new(Backend), channel.TestBackendID)
25+
test.SetRandomizer(newRandomizer(), channel.TestBackendID)
2526
}

backend/sim/wallet/wallet.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2020 - See NOTICE file for copyright holders.
1+
// Copyright 2025 - See NOTICE file for copyright holders.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -64,7 +64,6 @@ type Wallet struct {
6464
func (w *Wallet) Unlock(a wallet.Address) (wallet.Account, error) {
6565
w.accMutex.RLock()
6666
defer w.accMutex.RUnlock()
67-
6867
acc, ok := w.accs[wallet.Key(a)]
6968
if !ok {
7069
return nil, errors.Errorf("unlock unknown address: %v", a)
@@ -90,7 +89,6 @@ func (w *Wallet) LockAll() {
9089
func (w *Wallet) IncrementUsage(a wallet.Address) {
9190
w.accMutex.RLock()
9291
defer w.accMutex.RUnlock()
93-
9492
acc, ok := w.accs[wallet.Key(a)]
9593
if !ok {
9694
panic("invalid address")
@@ -106,7 +104,6 @@ func (w *Wallet) IncrementUsage(a wallet.Address) {
106104
func (w *Wallet) DecrementUsage(a wallet.Address) {
107105
w.accMutex.Lock()
108106
defer w.accMutex.Unlock()
109-
110107
acc, ok := w.accs[wallet.Key(a)]
111108
if !ok {
112109
panic("invalid address")
@@ -129,7 +126,6 @@ func (w *Wallet) DecrementUsage(a wallet.Address) {
129126
func (w *Wallet) UsageCount(a wallet.Address) int {
130127
w.accMutex.RLock()
131128
defer w.accMutex.RUnlock()
132-
133129
acc, ok := w.accs[wallet.Key(a)]
134130
if !ok {
135131
panic("invalid address")
@@ -153,15 +149,13 @@ func (w *Wallet) NewRandomAccount(rng *rand.Rand) wallet.Account {
153149
// account was already registered beforehand, an error is returned. Does not
154150
// lock or unlock the account.
155151
func (w *Wallet) AddAccount(acc *Account) error {
156-
key := wallet.Key(acc.Address())
157-
158152
w.accMutex.Lock()
159153
defer w.accMutex.Unlock()
160154

161-
if _, ok := w.accs[key]; ok {
155+
if _, ok := w.accs[wallet.Key(acc.Address())]; ok {
162156
return errors.New("duplicate insertion")
163157
}
164-
w.accs[key] = acc
158+
w.accs[wallet.Key(acc.Address())] = acc
165159

166160
return nil
167161
}
@@ -171,7 +165,6 @@ func (w *Wallet) AddAccount(acc *Account) error {
171165
func (w *Wallet) HasAccount(acc *Account) bool {
172166
w.accMutex.RLock()
173167
defer w.accMutex.RUnlock()
174-
175168
_, ok := w.accs[wallet.Key(acc.Address())]
176169
return ok
177170
}

0 commit comments

Comments
 (0)