Skip to content

Commit

Permalink
Feat multiple backends (#410)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* 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 <[email protected]>

* fix(all): Use map[int]ID instead of id for each backend.

Signed-off-by: Sophia Koehler <[email protected]>

* fix(all): Add map of IDs

Signed-off-by: Sophia Koehler <[email protected]>

* 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 <[email protected]>

* fix(Adjudicator): Change to singular channel ID in events.

Signed-off-by: Sophia Koehler <[email protected]>

* fix(client/test): Generalize role test.

Signed-off-by: Sophia Koehler <[email protected]>

* feat(channel): Add backend field check.
feat(client/test, wire): Add backendID arguments.

Signed-off-by: Sophia Koehler <[email protected]>

* fix(subchannel_dispute): Generalize event watcher.

Signed-off-by: Sophia Koehler <[email protected]>

* feat: Asset Address function to handle encoding in backends.

Signed-off-by: Sophia Koehler <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* chore: Remove unnecessary logs

Signed-off-by: Sophia Koehler <[email protected]>

* fix: Remove repeated assetIDs in LedgerID array

Signed-off-by: Sophia Koehler <[email protected]>

* chore: update go.sum, gofmt some files

Signed-off-by: Sophia Koehler <[email protected]>

* 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 <[email protected]>

* fix(golangci.yml): Exclude generated file from linter
chore: Refactor for linter

Signed-off-by: Sophia Koehler <[email protected]>

* fix(ci): Use go1.18 for the any type in proto
fix(golangci): Fix structure

Signed-off-by: Sophia Koehler <[email protected]>

* fix(ci): Use glinter 1.45 which supports go1.18

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): Add nolint flags for conversions

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): remove unnecessary flags

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): remove unnecessary flags

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): remove unnecessary flags

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): remove unnecessary flags

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): remove unnecessary flags

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): remove unnecessary flags

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): remove unnecessary flags

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): Rename and add comments to exported functions

Signed-off-by: Sophia Koehler <[email protected]>

* chore: Rename variables

Signed-off-by: Sophia Koehler <[email protected]>

* fix(params, address): Fix index allocation

Signed-off-by: Sophia Koehler <[email protected]>

* 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 <[email protected]>

* refactor: Name TestBackendID, rename multiLedgerID to LedgerBackendID

Signed-off-by: Sophia Koehler <[email protected]>

* refactor: Fix comment on exported function

Signed-off-by: Sophia Koehler <[email protected]>

* chore(all): Update license dates

Signed-off-by: Sophia Koehler <[email protected]>

* chore(backendtest): Rename to fix import issues

Signed-off-by: Sophia Koehler <[email protected]>

* chore: Update license date
fix: revert increased timeouts

Signed-off-by: Sophia Koehler <[email protected]>

---------

Signed-off-by: Sophia Koehler <[email protected]>
  • Loading branch information
sophia1ch authored Jan 29, 2025
1 parent 381fe48 commit b53c36b
Show file tree
Hide file tree
Showing 152 changed files with 3,610 additions and 1,961 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
release:

env:
go-version: 1.17
go-version: 1.18

jobs:
check-copyright:
Expand Down Expand Up @@ -39,7 +39,7 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.43
version: v1.45

- name: Lint proto files
uses: plexsystems/[email protected]
Expand Down
3 changes: 2 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ linters-settings:
# Default values:
- ^print.*$
- 'fmt\.Print.*'

exclude-rules:
- path: ".*\\.pb\\.go$" # Exclude protobuf generated files.
issues:
# Re-enable default excludes.
include:
Expand Down
4 changes: 2 additions & 2 deletions apps/payment/app_internal_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,7 +27,7 @@ import (

func TestApp_Def(t *testing.T) {
rng := pkgtest.Prng(t)
def := test.NewRandomAppID(rng)
def := test.NewRandomAppID(rng, channel.TestBackendID)
app := &App{def}
assert.True(t, app.Def().Equal(app.Def()))
}
Expand Down
8 changes: 5 additions & 3 deletions apps/payment/randomizer.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,8 @@ package payment
import (
"math/rand"

"perun.network/go-perun/wallet"

"perun.network/go-perun/channel"
"perun.network/go-perun/channel/test"
)
Expand All @@ -27,8 +29,8 @@ type Randomizer struct{}
var _ test.AppRandomizer = (*Randomizer)(nil)

// NewRandomApp always returns a payment app with a different address.
func (*Randomizer) NewRandomApp(rng *rand.Rand) channel.App {
return &App{test.NewRandomAppID(rng)}
func (*Randomizer) NewRandomApp(rng *rand.Rand, bID wallet.BackendID) channel.App {
return &App{test.NewRandomAppID(rng, bID)}
}

// NewRandomData returns NoData because a PaymentApp does not have data.
Expand Down
4 changes: 2 additions & 2 deletions apps/payment/randomizer_internal_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,7 +28,7 @@ func TestRandomizer(t *testing.T) {
rng := pkgtest.Prng(t)

r := new(Randomizer)
app := r.NewRandomApp(rng)
app := r.NewRandomApp(rng, channel.TestBackendID)
channel.RegisterApp(app)
regApp, err := channel.Resolve(app.Def())
assert.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions apps/payment/resolver_internal_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,7 +32,7 @@ func TestResolver(t *testing.T) {
rng := pkgtest.Prng(t)
assert, require := assert.New(t), require.New(t)

def := ctest.NewRandomAppID(rng)
def := ctest.NewRandomAppID(rng, channel.TestBackendID)
channel.RegisterAppResolver(def.Equal, &Resolver{})

app, err := channel.Resolve(def)
Expand Down
4 changes: 2 additions & 2 deletions backend/sim/channel/app.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -48,5 +48,5 @@ func (id AppID) Key() channel.AppIDKey {
// NewRandomAppID generates a new random app identifier.
func NewRandomAppID(rng *rand.Rand) AppID {
addr := wallet.NewRandomAddress(rng)
return AppID{addr}
return AppID{Address: addr}
}
8 changes: 7 additions & 1 deletion backend/sim/channel/asset.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -65,3 +65,9 @@ func (a Asset) Equal(b channel.Asset) bool {
}
return a.ID == simAsset.ID
}

// Address returns the address of the asset.
func (a Asset) Address() []byte {
data, _ := a.MarshalBinary()
return data
}
21 changes: 10 additions & 11 deletions backend/sim/channel/backend.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,23 +33,22 @@ type backend struct{}
var _ channel.Backend = new(backend)

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

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

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

if copy(id[:], w.Sum(nil)) != channel.IDLen {
log.Panic("Could not copy id")
err = errors.New("Could not copy id")
return
}
return
}
Expand Down Expand Up @@ -83,7 +82,7 @@ func (b *backend) NewAsset() channel.Asset {

// NewAppID returns an object of type AppID, which can be used for
// unmarshalling an app identifier from its binary representation.
func (b *backend) NewAppID() channel.AppID {
func (b *backend) NewAppID() (channel.AppID, error) {
addr := &simwallet.Address{}
return AppID{addr}
return AppID{addr}, nil
}
18 changes: 11 additions & 7 deletions backend/sim/channel/channel_internal_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,8 @@ package channel
import (
"testing"

"perun.network/go-perun/channel"

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

return &chtest.Setup{
Params: params,
Params2: params2,
State: state,
State2: state2,
Account: wtest.NewRandomAccount(rng),
RandomAddress: func() wallet.Address { return wtest.NewRandomAddress(rng) },
Params: params,
Params2: params2,
State: state,
State2: state2,
Account: wtest.NewRandomAccount(rng, channel.TestBackendID),
RandomAddress: func() map[wallet.BackendID]wallet.Address {
return wtest.NewRandomAddresses(rng, channel.TestBackendID)
},
}
}
8 changes: 4 additions & 4 deletions backend/sim/channel/init.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -22,9 +22,9 @@ import (
)

func init() {
channel.SetBackend(new(backend))
test.SetRandomizer(new(randomizer))
channel.SetBackend(new(backend), channel.TestBackendID)
test.SetRandomizer(new(randomizer), channel.TestBackendID)
test.SetNewRandomAppID(func(r *rand.Rand) channel.AppID {
return NewRandomAppID(r)
})
}, channel.TestBackendID)
}
4 changes: 2 additions & 2 deletions backend/sim/wallet/account.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -57,7 +57,7 @@ func NewRandomAccount(rng io.Reader) *Account {

// Address returns the address of this account.
func (a *Account) Address() wallet.Address {
return wallet.Address((*Address)(&a.privKey.PublicKey))
return (*Address)(&a.privKey.PublicKey)
}

// SignData is used to sign data with this account. If the account is locked,
Expand Down
32 changes: 28 additions & 4 deletions backend/sim/wallet/address.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -20,13 +20,20 @@ import (
"io"
"math/big"

"perun.network/go-perun/channel"

"perun.network/go-perun/log"
"perun.network/go-perun/wallet"
)

// Address represents a simulated address.
type Address ecdsa.PublicKey

// BackendID returns the backend id of the address.
func (a Address) BackendID() wallet.BackendID {
return channel.TestBackendID
}

const (
// elemLen is the length of the binary representation of a single element
// of the address in bytes.
Expand Down Expand Up @@ -54,6 +61,21 @@ func NewRandomAddress(rng io.Reader) *Address {
}
}

// NewRandomAddresses creates a new address using the randomness
// provided by rng.
func NewRandomAddresses(rng io.Reader) map[int]wallet.Address {
privateKey, err := ecdsa.GenerateKey(curve, rng)
if err != nil {
log.Panicf("Creation of account failed with error", err)
}

return map[int]wallet.Address{channel.TestBackendID: &Address{
Curve: privateKey.Curve,
X: privateKey.X,
Y: privateKey.Y,
}}
}

// Bytes converts this address to bytes.
func (a *Address) Bytes() []byte {
data := a.byteArray()
Expand Down Expand Up @@ -90,9 +112,11 @@ func (a *Address) Equal(addr wallet.Address) bool {
}

// Cmp checks the ordering of two addresses according to following definition:
// -1 if (a.X < addr.X) || ((a.X == addr.X) && (a.Y < addr.Y))
// 0 if (a.X == addr.X) && (a.Y == addr.Y)
// +1 if (a.X > addr.X) || ((a.X == addr.X) && (a.Y > addr.Y))
//
// -1 if (a.X < addr.X) || ((a.X == addr.X) && (a.Y < addr.Y))
// 0 if (a.X == addr.X) && (a.Y == addr.Y)
// +1 if (a.X > addr.X) || ((a.X == addr.X) && (a.Y > addr.Y))
//
// So the X coordinate is weighted higher.
// Pancis if the passed address is of the wrong type.
func (a *Address) Cmp(addr wallet.Address) int {
Expand Down
7 changes: 4 additions & 3 deletions backend/sim/wallet/init.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -15,11 +15,12 @@
package wallet

import (
"perun.network/go-perun/channel"
"perun.network/go-perun/wallet"
"perun.network/go-perun/wallet/test"
)

func init() {
wallet.SetBackend(new(Backend))
test.SetRandomizer(newRandomizer())
wallet.SetBackend(new(Backend), channel.TestBackendID)
test.SetRandomizer(newRandomizer(), channel.TestBackendID)
}
13 changes: 3 additions & 10 deletions backend/sim/wallet/wallet.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2020 - See NOTICE file for copyright holders.
// Copyright 2025 - See NOTICE file for copyright holders.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -64,7 +64,6 @@ type Wallet struct {
func (w *Wallet) Unlock(a wallet.Address) (wallet.Account, error) {
w.accMutex.RLock()
defer w.accMutex.RUnlock()

acc, ok := w.accs[wallet.Key(a)]
if !ok {
return nil, errors.Errorf("unlock unknown address: %v", a)
Expand All @@ -90,7 +89,6 @@ func (w *Wallet) LockAll() {
func (w *Wallet) IncrementUsage(a wallet.Address) {
w.accMutex.RLock()
defer w.accMutex.RUnlock()

acc, ok := w.accs[wallet.Key(a)]
if !ok {
panic("invalid address")
Expand All @@ -106,7 +104,6 @@ func (w *Wallet) IncrementUsage(a wallet.Address) {
func (w *Wallet) DecrementUsage(a wallet.Address) {
w.accMutex.Lock()
defer w.accMutex.Unlock()

acc, ok := w.accs[wallet.Key(a)]
if !ok {
panic("invalid address")
Expand All @@ -129,7 +126,6 @@ func (w *Wallet) DecrementUsage(a wallet.Address) {
func (w *Wallet) UsageCount(a wallet.Address) int {
w.accMutex.RLock()
defer w.accMutex.RUnlock()

acc, ok := w.accs[wallet.Key(a)]
if !ok {
panic("invalid address")
Expand All @@ -153,15 +149,13 @@ func (w *Wallet) NewRandomAccount(rng *rand.Rand) wallet.Account {
// account was already registered beforehand, an error is returned. Does not
// lock or unlock the account.
func (w *Wallet) AddAccount(acc *Account) error {
key := wallet.Key(acc.Address())

w.accMutex.Lock()
defer w.accMutex.Unlock()

if _, ok := w.accs[key]; ok {
if _, ok := w.accs[wallet.Key(acc.Address())]; ok {
return errors.New("duplicate insertion")
}
w.accs[key] = acc
w.accs[wallet.Key(acc.Address())] = acc

return nil
}
Expand All @@ -171,7 +165,6 @@ func (w *Wallet) AddAccount(acc *Account) error {
func (w *Wallet) HasAccount(acc *Account) bool {
w.accMutex.RLock()
defer w.accMutex.RUnlock()

_, ok := w.accs[wallet.Key(acc.Address())]
return ok
}
Loading

0 comments on commit b53c36b

Please sign in to comment.