diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b8e27396..6679361ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: release: env: - go-version: 1.18 + go-version: 1.22 jobs: check-copyright: @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Authors @@ -26,20 +26,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Check vanity import run: .scripts/check-vanity-imports.sh $GITHUB_WORKSPACE - name: Setup Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: ${{ env.go-version }} - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v7 with: - version: v1.45 + version: v2.1 - name: Lint proto files uses: plexsystems/protolint-action@v0.6.0 diff --git a/.golangci.json b/.golangci.json new file mode 100644 index 000000000..493d210a8 --- /dev/null +++ b/.golangci.json @@ -0,0 +1,103 @@ +{ + "formatters": { + "enable": [ + "gofmt", + "gofumpt", + "goimports" + ], + "exclusions": { + "generated": "lax", + "paths": [ + "third_party$", + "builtin$", + "examples$" + ] + } + }, + "linters": { + "default": "all", + "disable": [ + "err113", + "errorlint", + "gochecknoglobals", + "gochecknoinits", + "ireturn", + "lll", + "nlreturn", + "paralleltest", + "promlinter", + "tparallel", + "varnamelen", + "wrapcheck", + "wsl", + "testifylint", + "revive", + "recvcheck", + "prealloc", + "depguard", + "nonamedreturns", + "inamedparam", + "exhaustruct" + ], + "exclusions": { + "generated": "lax", + "paths": [ + "third_party$", + "builtin$", + "examples$" + ], + "presets": [ + "common-false-positives", + "legacy", + "std-error-handling" + ], + "rules": [ + { + "linters": [ + "err113", + "forcetypeassert", + "funlen" + ], + "path": "test" + }, + { + "linters": [ + "revive" + ], + "path": "test", + "text": "context-as-argument" + } + ] + }, + "settings": { + "cyclop": { + "max-complexity": 15 + }, + "forbidigo": { + "forbid": [ + { + "pattern": "^[Ee]quals$" + }, + { + "pattern": "^print.*$" + }, + { + "pattern": "fmt\\.Print.*" + } + ] + }, + "goheader": { + "template-path": ".scripts/copyright-notice", + "values": { + "regexp": { + "ANY_YEAR": "20(19|2\\d)" + } + } + } + } + }, + "run": { + "modules-download-mode": "readonly" + }, + "version": "2" +} \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 668e8353e..000000000 --- a/.golangci.yml +++ /dev/null @@ -1,81 +0,0 @@ -run: - timeout: 2m - - # Skip the eth bindings. - skip-dirs: - - backend/ethereum/bindings/ - - # Do not change go.{mod,sum}. - modules-download-mode: readonly - -linters: - enable-all: true - disable: - # Disabled as a style choice: - - wrapcheck # We do not rewrap all errors from other packages. - - varnamelen # We often use single letter arguments. - - exhaustivestruct # We often have uninitialized fields of structs. - - errorlint # We have interface errors which an impl needs to return. - - lll # We use long lines. - - gochecknoglobals # We have a lot of globals. - - nlreturn # "new line before return"; not useful. - - paralleltest # We like parallel tests. - - ireturn # We often return interfaces. - - wsl # Formatting disabled for now. - - gochecknoinits # We use init functions. - - gci # We have our own import order. - - goerr113 # We do not strictly require static errors. - - promlinter # Disabled because unstable. - - # These could be enabled in the future: - - ifshort # we often don't use `if err := …` for readability. - - tparallel # We don't always use parallel tests. - - # Deprecated: - - maligned - - scopelint - - golint - - interfacer - -linters-settings: - cyclop: - # 15 is used by go-report-card as well. - max-complexity: 15 - goheader: - values: - regexp: - ANY_YEAR: "20(19|2\\d)" # 2019-2029 - template-path: ".scripts/copyright-notice" - forbidigo: - forbid: - # Forbid functions to start with "get" or "Get". - - ^[Gg]et.*$ - - ^[Ee]quals$ - # Default values: - - ^print.*$ - - 'fmt\.Print.*' - exclude-rules: - - path: ".*\\.pb\\.go$" # Exclude protobuf generated files. -issues: - # Re-enable default excludes. - include: - - EXC0012 # revive: exported (.+) should have comment or be unexported - - EXC0013 # revive: package comment should be of the form "(.+)..." - - EXC0014 # revive: comment on exported (.+) should be of the form "(.+)..." - - EXC0015 # revive: package should have comment - - exclude-rules: - - path: test - linters: - # We often have long test or test helper functions. - - funlen - # Can use panicing interface casts. - - forcetypeassert - # Can create dynamic errors with errors.New. - - goerr113 - - # We always use testing.T as first argument in testing functions, - # therefore disable the "context must be the first argument" check in tests. - - path: test - linters: [revive] - text: "context-as-argument" diff --git a/apps/payment/app_internal_test.go b/apps/payment/app_internal_test.go index 19c46d5e4..7bcac626a 100644 --- a/apps/payment/app_internal_test.go +++ b/apps/payment/app_internal_test.go @@ -42,7 +42,7 @@ func TestApp_ValidInit(t *testing.T) { assert.Panics(func() { app.ValidInit(nil, wrongdata) }) //nolint:errcheck data := &channel.State{Data: Data()} - assert.Nil(app.ValidInit(nil, data)) + assert.NoError(app.ValidInit(nil, data)) } func TestApp_ValidTransition(t *testing.T) { @@ -93,9 +93,9 @@ func TestApp_ValidTransition(t *testing.T) { test.WithBalances(asBalances(tt.from...)...), ) numParticipants := len(tt.from[0]) - for i := 0; i < numParticipants; i++ { + for i := range numParticipants { // valid self-transition - assert.NoError(app.ValidTransition(nil, from, from, channel.Index(i))) + assert.NoError(app.ValidTransition(nil, from, from, channel.Index(i))) //nolint:gosec } for _, tto := range tt.tos { @@ -104,8 +104,8 @@ func TestApp_ValidTransition(t *testing.T) { test.WithAppData(Data()), test.WithBalances(asBalances(tto.alloc...)...), ) - for i := 0; i < numParticipants; i++ { - err := app.ValidTransition(nil, from, to, channel.Index(i)) + for i := range numParticipants { + err := app.ValidTransition(nil, from, to, channel.Index(i)) //nolint:gosec if i == tto.valid { assert.NoError(err) } else { diff --git a/apps/payment/randomizer_internal_test.go b/apps/payment/randomizer_internal_test.go index c178314cf..a16e5d679 100644 --- a/apps/payment/randomizer_internal_test.go +++ b/apps/payment/randomizer_internal_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" _ "perun.network/go-perun/backend/sim" // backend init "perun.network/go-perun/channel" @@ -31,7 +32,7 @@ func TestRandomizer(t *testing.T) { app := r.NewRandomApp(rng, channel.TestBackendID) channel.RegisterApp(app) regApp, err := channel.Resolve(app.Def()) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, app.Def().Equal(regApp.Def())) assert.True(t, IsData(r.NewRandomData(rng))) } diff --git a/apps/payment/resolver_internal_test.go b/apps/payment/resolver_internal_test.go index 9508a0346..e1428f21c 100644 --- a/apps/payment/resolver_internal_test.go +++ b/apps/payment/resolver_internal_test.go @@ -36,7 +36,7 @@ func TestResolver(t *testing.T) { channel.RegisterAppResolver(def.Equal, &Resolver{}) app, err := channel.Resolve(def) - assert.NoError(err) + require.NoError(err) require.NotNil(app) assert.True(def.Equal(app.Def())) } @@ -47,7 +47,7 @@ func TestData(t *testing.T) { assert.NotPanics(func() { data := Data() _, err := data.MarshalBinary() - assert.Nil(err) + assert.NoError(err) }) assert.NotPanics(func() { diff --git a/backend/sim/channel/app.go b/backend/sim/channel/app.go index 2c32d7e7c..ec7b70129 100644 --- a/backend/sim/channel/app.go +++ b/backend/sim/channel/app.go @@ -26,6 +26,12 @@ type AppID struct { *wallet.Address } +// NewRandomAppID generates a new random app identifier. +func NewRandomAppID(rng *rand.Rand) AppID { + addr := wallet.NewRandomAddress(rng) + return AppID{Address: addr} +} + // Equal returns whether the object is equal to the given object. func (id AppID) Equal(b channel.AppID) bool { bTyped, ok := b.(AppID) @@ -44,9 +50,3 @@ func (id AppID) Key() channel.AppIDKey { } return channel.AppIDKey(b) } - -// NewRandomAppID generates a new random app identifier. -func NewRandomAppID(rng *rand.Rand) AppID { - addr := wallet.NewRandomAddress(rng) - return AppID{Address: addr} -} diff --git a/backend/sim/channel/asset.go b/backend/sim/channel/asset.go index 2e66db169..403b07379 100644 --- a/backend/sim/channel/asset.go +++ b/backend/sim/channel/asset.go @@ -17,8 +17,10 @@ package channel import ( "encoding/binary" "fmt" + "math" "math/rand" + "github.com/pkg/errors" "perun.network/go-perun/channel" ) @@ -44,6 +46,9 @@ func NewRandomAsset(rng *rand.Rand) *Asset { // MarshalBinary marshals the address into its binary representation. func (a Asset) MarshalBinary() ([]byte, error) { data := make([]byte, assetLen) + if a.ID < 0 { + return nil, errors.New("asset ID must be non-negative") + } byteOrder.PutUint64(data, uint64(a.ID)) return data, nil } @@ -51,9 +56,13 @@ func (a Asset) MarshalBinary() ([]byte, error) { // UnmarshalBinary unmarshals the asset from its binary representation. func (a *Asset) UnmarshalBinary(data []byte) error { if len(data) != assetLen { - return fmt.Errorf("unexpected length %d, want %d", len(data), assetLen) //nolint:goerr113 // We do not want to define this as constant error. + return fmt.Errorf("unexpected length %d, want %d", len(data), assetLen) // We do not want to define this as constant error. + } + id := byteOrder.Uint64(data) + if id > math.MaxInt64 { + return fmt.Errorf("asset ID %d is too large", id) } - a.ID = int64(byteOrder.Uint64(data)) + a.ID = int64(id) return nil } diff --git a/backend/sim/channel/asset_test.go b/backend/sim/channel/asset_test.go index 7761e391e..b710b2e96 100644 --- a/backend/sim/channel/asset_test.go +++ b/backend/sim/channel/asset_test.go @@ -24,7 +24,7 @@ import ( func Test_Asset_GenericMarshaler(t *testing.T) { rng := pkgtest.Prng(t) - for n := 0; n < 10; n++ { + for range 10 { test.GenericMarshalerTest(t, &channel.Asset{ID: rng.Int63()}) } } diff --git a/backend/sim/wallet/address.go b/backend/sim/wallet/address.go index 562f517dd..9642181d2 100644 --- a/backend/sim/wallet/address.go +++ b/backend/sim/wallet/address.go @@ -29,6 +29,21 @@ import ( // Address represents a simulated address. type Address ecdsa.PublicKey +// NewRandomAddress creates a new address using the randomness +// provided by rng. +func NewRandomAddress(rng io.Reader) *Address { + privateKey, err := ecdsa.GenerateKey(curve, rng) + if err != nil { + log.Panicf("Creation of account failed with error", err) + } + + return &Address{ + Curve: privateKey.Curve, + X: privateKey.X, + Y: privateKey.Y, + } +} + // BackendID returns the backend id of the address. func (a Address) BackendID() wallet.BackendID { return channel.TestBackendID @@ -46,21 +61,6 @@ const ( // compile time check that we implement the perun Address interface. var _ wallet.Address = (*Address)(nil) -// NewRandomAddress creates a new address using the randomness -// provided by rng. -func NewRandomAddress(rng io.Reader) *Address { - privateKey, err := ecdsa.GenerateKey(curve, rng) - if err != nil { - log.Panicf("Creation of account failed with error", err) - } - - return &Address{ - Curve: privateKey.Curve, - X: privateKey.X, - Y: privateKey.Y, - } -} - // NewRandomAddresses creates a new address using the randomness // provided by rng. func NewRandomAddresses(rng io.Reader) map[wallet.BackendID]wallet.Address { @@ -82,19 +82,6 @@ func (a *Address) Bytes() []byte { return data[:] } -// byteArray converts an address into a 64-byte array. The returned array -// consists of two 32-byte chunks representing the public key's X and Y values. -func (a *Address) byteArray() (data [addrLen]byte) { - xb := a.X.Bytes() - yb := a.Y.Bytes() - - // Left-pad with 0 bytes. - copy(data[elemLen-len(xb):elemLen], xb) - copy(data[addrLen-len(yb):addrLen], yb) - - return data -} - // String converts this address to a human-readable string. func (a *Address) String() string { return fmt.Sprintf("0x%x", a.byteArray()) @@ -150,3 +137,16 @@ func (a *Address) UnmarshalBinary(data []byte) error { return nil } + +// byteArray converts an address into a 64-byte array. The returned array +// consists of two 32-byte chunks representing the public key's X and Y values. +func (a *Address) byteArray() (data [addrLen]byte) { + xb := a.X.Bytes() + yb := a.Y.Bytes() + + // Left-pad with 0 bytes. + copy(data[elemLen-len(xb):elemLen], xb) + copy(data[addrLen-len(yb):addrLen], yb) + + return data +} diff --git a/backend/sim/wallet/address_internal_test.go b/backend/sim/wallet/address_internal_test.go index c3f5e703f..41d9c6494 100644 --- a/backend/sim/wallet/address_internal_test.go +++ b/backend/sim/wallet/address_internal_test.go @@ -19,6 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" pkgtest "polycry.pt/poly-go/test" "perun.network/go-perun/wire/test" @@ -26,7 +27,7 @@ import ( func TestGenericMarshaler(t *testing.T) { rng := pkgtest.Prng(t) - for n := 0; n < 10; n++ { + for range 10 { test.GenericMarshalerTest(t, NewRandomAddress(rng)) } } @@ -43,13 +44,13 @@ func TestAddressMarshalling(t *testing.T) { Y: new(big.Int).SetBytes(dest[elemLen:]), } result, err := addr.MarshalBinary() - assert.NoError(t, err, "marshaling address should not error") + require.NoError(t, err, "marshaling address should not error") assert.Equal(t, result, dest[:]) }) t.Run("half length", func(t *testing.T) { const zeros = 5 - for i := 0; i < zeros; i++ { + for i := range zeros { dest[i] = 0 dest[i+elemLen] = 0 } @@ -59,7 +60,7 @@ func TestAddressMarshalling(t *testing.T) { Y: new(big.Int).SetBytes(dest[elemLen:]), } result, err := addr.MarshalBinary() - assert.NoError(t, err, "marshaling address should not error") + require.NoError(t, err, "marshaling address should not error") assert.Equal(t, result, dest[:]) }) } @@ -73,7 +74,7 @@ func TestAddressOrdering(t *testing.T) { expected int } var cases []addrTest - for i := 0; i < 10; i++ { + for range 10 { addr := NewRandomAddress(rng) ltX := CloneAddr(addr) ltY := CloneAddr(addr) diff --git a/backend/sim/wallet/wallet.go b/backend/sim/wallet/wallet.go index 37f431153..3665471d6 100644 --- a/backend/sim/wallet/wallet.go +++ b/backend/sim/wallet/wallet.go @@ -27,6 +27,16 @@ import ( var _ wallet.Wallet = (*Wallet)(nil) +// Wallet is a collection of accounts. Query accounts using Unlock, track their +// usage using IncrementUsage and DecrementUsage, and lock them using LockAll. +// Create new accounts using NewRandomAccount, and add existing accounts using +// AddAccount. Check whether the wallet owns a particular account via +// HasAccount. +type Wallet struct { + accMutex sync.RWMutex + accs map[wallet.AddrKey]*Account +} + // NewWallet creates a new empty wallet. func NewWallet() *Wallet { return &Wallet{accs: make(map[wallet.AddrKey]*Account)} @@ -48,16 +58,6 @@ func NewRestoredWallet(accounts ...*Account) *Wallet { return w } -// Wallet is a collection of accounts. Query accounts using Unlock, track their -// usage using IncrementUsage and DecrementUsage, and lock them using LockAll. -// Create new accounts using NewRandomAccount, and add existing accounts using -// AddAccount. Check whether the wallet owns a particular account via -// HasAccount. -type Wallet struct { - accMutex sync.RWMutex - accs map[wallet.AddrKey]*Account -} - // Unlock retrieves the account belonging to the supplied address, and unlocks // it. If the address does not have a corresponding account in the wallet, // returns an error. diff --git a/backend/sim/wallet/wallet_internal_test.go b/backend/sim/wallet/wallet_internal_test.go index b6f6a4d7f..9dbea3284 100644 --- a/backend/sim/wallet/wallet_internal_test.go +++ b/backend/sim/wallet/wallet_internal_test.go @@ -33,7 +33,7 @@ func TestSignatureSerialize(t *testing.T) { rng := pkgtest.Prng(t) // More iterations are better for catching value dependent bugs - for i := 0; i < 10; i++ { + for range 10 { rBytes := make([]byte, 32) sBytes := make([]byte, 32) @@ -45,11 +45,11 @@ func TestSignatureSerialize(t *testing.T) { s := new(big.Int).SetBytes(sBytes) sig, err1 := serializeSignature(r, s) - a.Nil(err1, "Serialization should not fail") - a.Equal(curve.Params().BitSize/4, len(sig), "Signature has wrong size") + a.NoError(err1, "Serialization should not fail") + a.Len(sig, curve.Params().BitSize/4, "Signature has wrong size") R, S, err2 := deserializeSignature(sig) - a.Nil(err2, "Deserialization should not fail") + a.NoError(err2, "Deserialization should not fail") a.Equal(r, R, "Serialized and deserialized r values should be equal") a.Equal(s, S, "Serialized and deserialized s values should be equal") } @@ -71,7 +71,7 @@ func TestGenericTests(t *testing.T) { // NewRandomAddress is also tested in channel_test but since they are two packages, // we also need to test it here rng := pkgtest.Prng(t) - for i := 0; i < 10; i++ { + for range 10 { addr0 := NewRandomAddress(rng) addr1 := NewRandomAddress(rng) assert.NotEqual( @@ -80,10 +80,10 @@ func TestGenericTests(t *testing.T) { addrStrLen := addrLen*2 + 2 // hex encoded and prefixed with 0x str0 := addr0.String() str1 := addr1.String() - assert.Equal( - t, addrStrLen, len(str0), "First address '%v' has wrong length", str0) - assert.Equal( - t, addrStrLen, len(str1), "Second address '%v' has wrong length", str1) + assert.Len( + t, str0, addrStrLen, "First address '%v' has wrong length", str0) + assert.Len( + t, str1, addrStrLen, "Second address '%v' has wrong length", str1) assert.NotEqual( t, str0, str1, "Printed addresses are unlikely to be identical") } diff --git a/backend/sim/wallet/wallet_test.go b/backend/sim/wallet/wallet_test.go index 1f1989b00..c71ec6b91 100644 --- a/backend/sim/wallet/wallet_test.go +++ b/backend/sim/wallet/wallet_test.go @@ -30,7 +30,7 @@ func TestWallet_AddAccount(t *testing.T) { acc := wallet.NewRandomAccount(rng) assert.False(t, w.HasAccount(acc)) - assert.NoError(t, w.AddAccount(acc)) + require.NoError(t, w.AddAccount(acc)) assert.True(t, w.HasAccount(acc)) assert.Error(t, w.AddAccount(acc)) } diff --git a/backend/sim/wire/account.go b/backend/sim/wire/account.go index 191cbcd17..bb509d9c4 100644 --- a/backend/sim/wire/account.go +++ b/backend/sim/wire/account.go @@ -25,6 +25,13 @@ type Account struct { addr wire.Address } +// NewRandomAccount generates a new random account. +func NewRandomAccount(rng *rand.Rand) *Account { + return &Account{ + addr: NewRandomAddress(rng), + } +} + // Address returns the account's address. func (acc *Account) Address() wire.Address { return acc.addr @@ -34,10 +41,3 @@ func (acc *Account) Address() wire.Address { func (acc *Account) Sign(msg []byte) ([]byte, error) { return []byte("Authenticate"), nil } - -// NewRandomAccount generates a new random account. -func NewRandomAccount(rng *rand.Rand) *Account { - return &Account{ - addr: NewRandomAddress(rng), - } -} diff --git a/backend/sim/wire/address.go b/backend/sim/wire/address.go index 4c241dc5c..d43d50c61 100644 --- a/backend/sim/wire/address.go +++ b/backend/sim/wire/address.go @@ -33,6 +33,16 @@ func NewAddress() *Address { return &Address{} } +// NewRandomAddress returns a new random peer address. +func NewRandomAddress(rng *rand.Rand) *Address { + addr := Address{} + _, err := rng.Read(addr[:]) + if err != nil { + panic(err) + } + return &addr +} + // MarshalBinary marshals the address to binary. func (a Address) MarshalBinary() (data []byte, err error) { return a[:], nil @@ -70,13 +80,3 @@ func (a Address) Verify(msg, sig []byte) error { } return nil } - -// NewRandomAddress returns a new random peer address. -func NewRandomAddress(rng *rand.Rand) *Address { - addr := Address{} - _, err := rng.Read(addr[:]) - if err != nil { - panic(err) - } - return &addr -} diff --git a/channel/actionmachine.go b/channel/actionmachine.go index 453b67a1e..ecd119f23 100644 --- a/channel/actionmachine.go +++ b/channel/actionmachine.go @@ -114,13 +114,6 @@ func (m *ActionMachine) Update() error { return nil } -// setStaging sets the current staging phase and state and additionally clears -// the staging actions. -func (m *ActionMachine) setStaging(phase Phase, state *State) { - m.stagingActions = make([]Action, m.N()) - m.machine.setStaging(phase, state) -} - // Clone returns a deep copy of ActionMachine. func (m *ActionMachine) Clone() *ActionMachine { clonedActions := make([]Action, m.N()) @@ -144,3 +137,10 @@ func (m *ActionMachine) Clone() *ActionMachine { stagingActions: clonedActions, } } + +// setStaging sets the current staging phase and state and additionally clears +// the staging actions. +func (m *ActionMachine) setStaging(phase Phase, state *State) { + m.stagingActions = make([]Action, m.N()) + m.machine.setStaging(phase, state) +} diff --git a/channel/adjudicator.go b/channel/adjudicator.go index ffb5dc33d..dc020af39 100644 --- a/channel/adjudicator.go +++ b/channel/adjudicator.go @@ -204,7 +204,7 @@ type ( } // StateMap represents a channel state tree. - StateMap map[ID]*State + StateMap map[ID]*SignedState ) // NewProgressReq creates a new ProgressReq object. @@ -302,12 +302,12 @@ func (t *TimeTimeout) String() string { // MakeStateMap creates a new StateMap object. func MakeStateMap() StateMap { - return make(map[ID]*State) + return make(map[ID]*SignedState) } // Add adds the given states to the state map. -func (m StateMap) Add(states ...*State) { +func (m StateMap) Add(states ...*SignedState) { for _, s := range states { - m[s.ID] = s + m[s.State.ID] = s } } diff --git a/channel/allocation.go b/channel/allocation.go index 8727ca2ed..4b21c4273 100644 --- a/channel/allocation.go +++ b/channel/allocation.go @@ -18,6 +18,7 @@ import ( "encoding" "io" "log" + "math" "math/big" "perun.network/go-perun/wallet" @@ -127,6 +128,9 @@ func NewAllocation(numParts int, backends []wallet.BackendID, assets ...Asset) * func (a *Allocation) AssetIndex(asset Asset) (Index, bool) { for idx, _asset := range a.Assets { if asset.Equal(_asset) { + if idx < 0 || idx >= math.MaxUint16 { + log.Panicf("asset index out of bounds: %d", idx) + } return Index(idx), true } } @@ -298,6 +302,80 @@ func (b Balances) Sub(a Balances) Balances { ) } +// Sum returns the sum of each asset over all participants. +func (b Balances) Sum() []Bal { + n := len(b) + totals := make([]*big.Int, n) + for i := range n { + totals[i] = new(big.Int) + } + + for i, asset := range b { + for _, bal := range asset { + totals[i].Add(totals[i], bal) + } + } + return totals +} + +// Decode decodes a Balances from an io.Reader. +func (b *Balances) Decode(r io.Reader) error { + var numAssets, numParts Index + if err := perunio.Decode(r, &numAssets, &numParts); err != nil { + return errors.WithMessage(err, "decoding dimensions") + } + if numAssets > MaxNumAssets { + return errors.Errorf("expected maximum number of assets %d, got %d", MaxNumAssets, numAssets) + } + if numParts > MaxNumParts { + return errors.Errorf("expected maximum number of parts %d, got %d", MaxNumParts, numParts) + } + + *b = make(Balances, numAssets) + for i := range *b { + (*b)[i] = make([]Bal, numParts) + for j := range (*b)[i] { + (*b)[i][j] = new(big.Int) + if err := perunio.Decode(r, &(*b)[i][j]); err != nil { + return errors.WithMessagef( + err, "decoding balance of asset %d of participant %d", i, j) + } + } + } + return nil +} + +// Encode encodes these balances into an io.Writer. +func (b Balances) Encode(w io.Writer) error { + numAssets := len(b) + numParts := 0 + + if numAssets > 0 { + numParts = len(b[0]) + } + if numAssets > MaxNumAssets { + return errors.Errorf("expected maximum number of assets %d, got %d", MaxNumAssets, numAssets) + } + if numParts > MaxNumParts { + return errors.Errorf("expected maximum number of parts %d, got %d", MaxNumParts, numParts) + } + if numParts < 0 || numParts > math.MaxUint16 { + return errors.New("too many participants") + } + if err := perunio.Encode(w, Index(numAssets), Index(numParts)); err != nil { + return errors.WithMessage(err, "encoding dimensions") + } + for i := range b { + for j := range b[i] { + if err := perunio.Encode(w, b[i][j]); err != nil { + return errors.WithMessagef( + err, "encoding balance of asset %d of participant %d", i, j) + } + } + } + return nil +} + // operate returns op(b, a). It panics if the dimensions do not match. func (b Balances) operate(a Balances, op func(Bal, Bal) Bal) Balances { if len(a) != len(b) { @@ -325,12 +403,29 @@ func (a Allocation) Encode(w io.Writer) error { err, "invalid allocations cannot be encoded, got %v", a) } // encode dimensions - if err := perunio.Encode(w, Index(len(a.Assets)), Index(len(a.Balances[0])), Index(len(a.Locked))); err != nil { + assetLen := len(a.Assets) + if assetLen > math.MaxUint16 { + return errors.New("too many assets") + } + balanceLen := len(a.Balances[0]) + if balanceLen > math.MaxUint16 { + return errors.New("too many participants") + } + lockedLen := len(a.Locked) + if lockedLen > math.MaxUint16 { + return errors.New("too many sub-allocations") + } + + if err := perunio.Encode(w, Index(assetLen), Index(balanceLen), Index(lockedLen)); err != nil { return err } // encode assets for i, asset := range a.Assets { - if err := perunio.Encode(w, uint32(a.Backends[i])); err != nil { + id := int(a.Backends[i]) + if id < 0 || id > math.MaxUint32 { + return errors.New("asset index out of bounds") + } + if err := perunio.Encode(w, uint32(id)); err != nil { return errors.WithMessagef(err, "encoding backends %d", i) } if err := perunio.Encode(w, asset); err != nil { @@ -394,62 +489,6 @@ func (a *Allocation) Decode(r io.Reader) error { return a.Valid() } -// Decode decodes a Balances from an io.Reader. -func (b *Balances) Decode(r io.Reader) error { - var numAssets, numParts Index - if err := perunio.Decode(r, &numAssets, &numParts); err != nil { - return errors.WithMessage(err, "decoding dimensions") - } - if numAssets > MaxNumAssets { - return errors.Errorf("expected maximum number of assets %d, got %d", MaxNumAssets, numAssets) - } - if numParts > MaxNumParts { - return errors.Errorf("expected maximum number of parts %d, got %d", MaxNumParts, numParts) - } - - *b = make(Balances, numAssets) - for i := range *b { - (*b)[i] = make([]Bal, numParts) - for j := range (*b)[i] { - (*b)[i][j] = new(big.Int) - if err := perunio.Decode(r, &(*b)[i][j]); err != nil { - return errors.WithMessagef( - err, "decoding balance of asset %d of participant %d", i, j) - } - } - } - return nil -} - -// Encode encodes these balances into an io.Writer. -func (b Balances) Encode(w io.Writer) error { - numAssets := len(b) - numParts := 0 - - if numAssets > 0 { - numParts = len(b[0]) - } - if numAssets > MaxNumAssets { - return errors.Errorf("expected maximum number of assets %d, got %d", MaxNumAssets, numAssets) - } - if numParts > MaxNumParts { - return errors.Errorf("expected maximum number of parts %d, got %d", MaxNumParts, numParts) - } - - if err := perunio.Encode(w, Index(numAssets), Index(numParts)); err != nil { - return errors.WithMessage(err, "encoding dimensions") - } - for i := range b { - for j := range b[i] { - if err := perunio.Encode(w, b[i][j]); err != nil { - return errors.WithMessagef( - err, "encoding balance of asset %d of participant %d", i, j) - } - } - } - return nil -} - // CloneBals creates a deep copy of a balance array. func CloneBals(orig []Bal) []Bal { if orig == nil { @@ -535,22 +574,6 @@ func (a Allocation) Sum() []Bal { return totals } -// Sum returns the sum of each asset over all participants. -func (b Balances) Sum() []Bal { - n := len(b) - totals := make([]*big.Int, n) - for i := 0; i < n; i++ { - totals[i] = new(big.Int) - } - - for i, asset := range b { - for _, bal := range asset { - totals[i].Add(totals[i], bal) - } - } - return totals -} - // NewSubAlloc creates a new sub-allocation. func NewSubAlloc(id ID, bals []Bal, indexMap []Index) *SubAlloc { if indexMap == nil { @@ -607,7 +630,7 @@ func (a *Allocation) Equal(b *Allocation) error { } // Compare Balances - if err := a.Balances.AssertEqual(b.Balances); err != nil { + if err := a.AssertEqual(b.Balances); err != nil { return errors.WithMessage(err, "comparing balances") } @@ -667,7 +690,11 @@ func (s SubAlloc) Encode(w io.Writer) error { err, "invalid sub-allocations cannot be encoded, got %v", s) } // encode ID and dimension - if err := perunio.Encode(w, s.ID, Index(len(s.Bals))); err != nil { + balsLen := len(s.Bals) + if balsLen > math.MaxUint16 { + return errors.New("too many bals") + } + if err := perunio.Encode(w, s.ID, Index(balsLen)); err != nil { return errors.WithMessagef( err, "encoding sub-allocation ID or dimension, id %v", s.ID) } @@ -679,7 +706,11 @@ func (s SubAlloc) Encode(w io.Writer) error { } } // Encode IndexMap. - if err := perunio.Encode(w, Index(len(s.IndexMap))); err != nil { + idxMapLen := len(s.IndexMap) + if idxMapLen > math.MaxUint16 { + return errors.New("too many index map entries") + } + if err := perunio.Encode(w, Index(idxMapLen)); err != nil { return errors.WithMessage(err, "encoding length of index map") } for i, x := range s.IndexMap { diff --git a/channel/allocation_test.go b/channel/allocation_test.go index 74f8cabcc..d9904a86a 100644 --- a/channel/allocation_test.go +++ b/channel/allocation_test.go @@ -163,7 +163,7 @@ func TestBalancesGreaterOrEqual(t *testing.T) { func TestBalancesEqualSum(t *testing.T) { rng := pkgtest.Prng(t) - for i := 0; i < 10; i++ { + for range 10 { // Two random balances are different by chance. a, b := test.NewRandomBalances(rng), test.NewRandomBalances(rng) ok, err := pkgbig.EqualSum(a, b) @@ -233,7 +233,7 @@ func testBalancesOperation(t *testing.T, op func(channel.Balances, channel.Balan func TestBalancesSerialization(t *testing.T) { rng := pkgtest.Prng(t) - for n := 0; n < 10; n++ { + for range 10 { alloc := test.NewRandomAllocation(rng) if alloc.Valid() == nil { peruniotest.GenericSerializerTest(t, alloc) diff --git a/channel/app.go b/channel/app.go index cd9d5305f..eaf8135c1 100644 --- a/channel/app.go +++ b/channel/app.go @@ -161,7 +161,7 @@ func (e OptAppEnc) Encode(w io.Writer) error { if IsNoApp(e.App) { return perunio.Encode(w, false) } - return perunio.Encode(w, true, e.App.Def()) + return perunio.Encode(w, true, e.Def()) } // Encode encodes an optional App value. @@ -221,7 +221,7 @@ func (d OptAppDecMap) Decode(r io.Reader) (err error) { return err } *d.App = make(map[int]App, mapLen) - for i := 0; i < mapLen; i++ { + for range mapLen { var key int if err := perunio.Decode(r, &key); err != nil { return err diff --git a/channel/app_test.go b/channel/app_test.go index 65c593263..c106efd66 100644 --- a/channel/app_test.go +++ b/channel/app_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/channel" "perun.network/go-perun/channel/test" pkgtest "polycry.pt/poly-go/test" @@ -31,8 +32,8 @@ func TestAppShouldEqual(t *testing.T) { assert.EqualError(t, channel.AppShouldEqual(app1, app2), "different App definitions") assert.EqualError(t, channel.AppShouldEqual(app2, app1), "different App definitions") - assert.NoError(t, channel.AppShouldEqual(app1, app1)) + require.NoError(t, channel.AppShouldEqual(app1, app1)) assert.EqualError(t, channel.AppShouldEqual(app1, napp), "(non-)nil App definitions") assert.EqualError(t, channel.AppShouldEqual(napp, app1), "(non-)nil App definitions") - assert.NoError(t, channel.AppShouldEqual(napp, napp)) + require.NoError(t, channel.AppShouldEqual(napp, napp)) } diff --git a/channel/appregistry_internal_test.go b/channel/appregistry_internal_test.go index 08e74606e..b81d51d56 100644 --- a/channel/appregistry_internal_test.go +++ b/channel/appregistry_internal_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "polycry.pt/poly-go/test" ) @@ -97,7 +98,7 @@ func testAppRegistryIdentity(t *testing.T, rng *rand.Rand) { func assertIdentity(t *testing.T, expected App) { t.Helper() actual, err := Resolve(expected.Def()) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, actual.Def().Equal(expected.Def())) } diff --git a/channel/funder_internal_test.go b/channel/funder_internal_test.go index ee362113d..83060e452 100644 --- a/channel/funder_internal_test.go +++ b/channel/funder_internal_test.go @@ -34,7 +34,7 @@ func TestAssetFundingError(t *testing.T) { assert.Equal(Index(2), perr.TimedOutPeers[1]) assert.Equal(Index(3), perr.TimedOutPeers[2]) assert.Equal(Index(4), perr.TimedOutPeers[3]) - assert.Equal(4, len(perr.TimedOutPeers)) + assert.Len(perr.TimedOutPeers, 4) assert.Equal(perr.Error(), "Funding Error on asset [42] peers: [1], [2], [3], [4], did not fund channel in time") assert.False(IsAssetFundingError(errors.New("not a asset funding error"))) } @@ -61,7 +61,8 @@ func TestFundingTimeoutError(t *testing.T) { assert.Equal(Index(1), perr.Errors[2].TimedOutPeers[0]) assert.Equal(Index(3), perr.Errors[2].TimedOutPeers[1]) assert.Equal(3, len(perr.Errors)) - assert.Equal(perr.Error(), "Funding Error on asset [42] peers: [1], [2], did not fund channel in time; Funding Error on asset [1337] peers: [0], [2], did not fund channel in time; Funding Error on asset [7531] peers: [1], [3], did not fund channel in time; ") + assert.Equal("Funding Error on asset [42] peers: [1], [2], did not fund channel in time; Funding Error on asset [1337] peers: [0], [2], did not fund channel in time; Funding Error on asset [7531] peers: [1], [3], did not fund channel in time; ", + perr.Error()) // test no funding timeout error assert.False(IsFundingTimeoutError(errors.New("no FundingTimeoutError"))) // nil input should not return error diff --git a/channel/machine.go b/channel/machine.go index 333ca8205..2d41ff728 100644 --- a/channel/machine.go +++ b/channel/machine.go @@ -17,6 +17,7 @@ package channel import ( "fmt" stdio "io" + "math" "github.com/pkg/errors" @@ -147,6 +148,9 @@ func newMachine(acc map[wallet.BackendID]wallet.Account, params Params) (*machin if idx < 0 { return nil, errors.New("account not part of participant set") } + if idx > math.MaxUint16 { + return nil, errors.New("index out of bounds") + } return &machine{ phase: InitActing, @@ -190,7 +194,11 @@ func (m *machine) Params() *Params { // N returns the number of participants of the channel parameters of this machine. func (m *machine) N() Index { - return Index(len(m.params.Parts)) + partsLen := len(m.params.Parts) + if partsLen > math.MaxUint16 { + panic("number of participants exceeds uint16") + } + return Index(partsLen) } // Phase returns the current phase. @@ -198,12 +206,6 @@ func (m *machine) Phase() Phase { return m.phase } -// setPhase is internally used to set the phase. -func (m *machine) setPhase(p Phase) { - m.Log().Tracef("phase transition: %v", PhaseTransition{m.phase, p}) - m.phase = p -} - // inPhase returns whether phase is in phases. func inPhase(phase Phase, phases []Phase) bool { for _, p := range phases { @@ -243,7 +245,7 @@ func (m *machine) State() *State { return m.currentTX.State } -// CurrentTX returns the current current transaction. +// CurrentTX returns the current transaction. func (m *machine) CurrentTX() Transaction { return m.currentTX } @@ -303,12 +305,6 @@ func (m *machine) AddSig(idx Index, sig wallet.Sig) error { return nil } -// setStaging sets the given phase and state as staging state. -func (m *machine) setStaging(phase Phase, state *State) { - m.stagingTX = *m.newTransaction(state) - m.setPhase(phase) -} - // DiscardUpdate discards the current staging transaction and sets the machine's // phase back to Acting. This method is useful in the case where a valid update // request is rejected. @@ -340,35 +336,6 @@ func (m *machine) EnableFinal() error { return m.enableStaged(PhaseTransition{Signing, Final}) } -// enableStaged checks that -// 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 { - if err := m.expect(expected); err != nil { - return errors.WithMessage(err, "no staging phase") - } - - // Assert that we transition to phase Final iff state.IsFinal. - if (expected.To == Final) != m.stagingTX.State.IsFinal { - return m.phaseErrorf(expected, "State.IsFinal and target phase don't match") - } - - // Assert that all signatures are present. - for i, sig := range m.stagingTX.Sigs { - if sig == nil { - return m.phaseErrorf(expected, "signature %d missing from staging TX", i) - } - } - - m.setPhase(expected.To) - m.addTx(&m.stagingTX) - - return nil -} - // SetFunded tells the state machine that the channel got funded and progresses // to the Acting phase. func (m *machine) SetFunded() error { @@ -437,15 +404,6 @@ func (m *machine) SetWithdrawn() error { return m.simplePhaseTransition(Withdrawing, Withdrawn) } -func (m *machine) simplePhaseTransition(from, to Phase) error { - if err := m.expect(PhaseTransition{from, to}); err != nil { - return err - } - - m.setPhase(to) - return nil -} - var validPhaseTransitions = map[PhaseTransition]struct{}{ {InitActing, InitSigning}: {}, {InitSigning, Funding}: {}, @@ -469,14 +427,25 @@ var validPhaseTransitions = map[PhaseTransition]struct{}{ {Withdrawing, Withdrawn}: {}, } -func (m *machine) expect(tr PhaseTransition) error { - if m.phase != tr.From { - return m.phaseErrorf(tr, "not in correct phase") +func (m *machine) Clone() *machine { + var prevTXs []Transaction + if m.prevTXs != nil { + prevTXs = make([]Transaction, len(m.prevTXs)) + for i, tx := range m.prevTXs { + prevTXs[i] = tx.Clone() + } } - if _, ok := validPhaseTransitions[PhaseTransition{m.phase, tr.To}]; !ok { - return m.phaseErrorf(tr, "forbidden phase transition") + + return &machine{ + phase: m.phase, + acc: m.acc, + idx: m.idx, + params: *m.params.Clone(), + stagingTX: m.stagingTX.Clone(), + currentTX: m.currentTX.Clone(), + prevTXs: prevTXs, + Embedding: m.Embedding, } - return nil } // ValidTransition checks that the transition from the current to the provided @@ -506,7 +475,7 @@ func (m *machine) ValidTransition(to *State) error { return newError(fmt.Sprintf("expected version %d, got version %d", m.currentTX.Version+1, to.Version)) } - if err := to.Allocation.Valid(); err != nil { + if err := to.Valid(); err != nil { return newError(fmt.Sprintf("invalid allocation: %v", err)) } @@ -523,6 +492,60 @@ func (m *machine) ValidTransition(to *State) error { return nil } +func (m *machine) IsRegistered() bool { + return m.phase >= Registered +} + +// setPhase is internally used to set the phase. +func (m *machine) setPhase(p Phase) { + m.Log().Tracef("phase transition: %v", PhaseTransition{m.phase, p}) + m.phase = p +} + +// setStaging sets the given phase and state as staging state. +func (m *machine) setStaging(phase Phase, state *State) { + m.stagingTX = *m.newTransaction(state) + m.setPhase(phase) +} + +// enableStaged checks that +// 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 { + if err := m.expect(expected); err != nil { + return errors.WithMessage(err, "no staging phase") + } + + // Assert that we transition to phase Final iff state.IsFinal. + if (expected.To == Final) != m.stagingTX.IsFinal { + return m.phaseErrorf(expected, "State.IsFinal and target phase don't match") + } + + // Assert that all signatures are present. + for i, sig := range m.stagingTX.Sigs { + if sig == nil { + return m.phaseErrorf(expected, "signature %d missing from staging TX", i) + } + } + + m.setPhase(expected.To) + m.addTx(&m.stagingTX) + + return nil +} + +func (m *machine) simplePhaseTransition(from, to Phase) error { + if err := m.expect(PhaseTransition{from, to}); err != nil { + return err + } + + m.setPhase(to) + return nil +} + // phaseErrorf constructs a new PhaseTransitionError. func (m *machine) phaseErrorf(expected PhaseTransition, format string, args ...interface{}) error { return newPhaseTransitionErrorf(m.params.ID(), m.phase, expected, format, args...) @@ -533,29 +556,14 @@ func (m *machine) selfTransition() PhaseTransition { return PhaseTransition{m.phase, m.phase} } -func (m *machine) Clone() *machine { - var prevTXs []Transaction - if m.prevTXs != nil { - prevTXs = make([]Transaction, len(m.prevTXs)) - for i, tx := range m.prevTXs { - prevTXs[i] = tx.Clone() - } +func (m *machine) expect(tr PhaseTransition) error { + if m.phase != tr.From { + return m.phaseErrorf(tr, "not in correct phase") } - - return &machine{ - phase: m.phase, - acc: m.acc, - idx: m.idx, - params: *m.params.Clone(), - stagingTX: m.stagingTX.Clone(), - currentTX: m.currentTX.Clone(), - prevTXs: prevTXs, - Embedding: m.Embedding, + if _, ok := validPhaseTransitions[PhaseTransition{m.phase, tr.To}]; !ok { + return m.phaseErrorf(tr, "forbidden phase transition") } -} - -func (m *machine) IsRegistered() bool { - return m.phase >= Registered + return nil } func (m *machine) newTransaction(s *State) *Transaction { diff --git a/channel/mock_app_internal_test.go b/channel/mock_app_internal_test.go index c021eacc3..6c949273a 100644 --- a/channel/mock_app_internal_test.go +++ b/channel/mock_app_internal_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" wiretest "perun.network/go-perun/wire/test" pkgtest "polycry.pt/poly-go/test" @@ -70,19 +71,19 @@ func MockStateAppTest(t *testing.T, app MockApp) { t.Run("ValidTransition", func(t *testing.T) { // ValidTransition only checks the first state. - assert.NoError(t, app.ValidTransition(nil, stateValid, nil, 0)) + require.NoError(t, app.ValidTransition(nil, stateValid, nil, 0)) assert.Error(t, app.ValidTransition(nil, stateErr, nil, 0)) assert.True(t, IsStateTransitionError(app.ValidTransition(nil, stateTransErr, nil, 0))) assert.True(t, IsActionError(app.ValidTransition(nil, stateActErr, nil, 0))) - assert.Panics(t, func() { assert.NoError(t, app.ValidTransition(nil, statePanic, nil, 0)) }) + assert.Panics(t, func() { require.NoError(t, app.ValidTransition(nil, statePanic, nil, 0)) }) }) t.Run("ValidInit", func(t *testing.T) { - assert.NoError(t, app.ValidInit(nil, stateValid)) + require.NoError(t, app.ValidInit(nil, stateValid)) assert.Error(t, app.ValidInit(nil, stateErr)) assert.True(t, IsStateTransitionError(app.ValidInit(nil, stateTransErr))) assert.True(t, IsActionError(app.ValidInit(nil, stateActErr))) - assert.Panics(t, func() { assert.NoError(t, app.ValidInit(nil, statePanic)) }) + assert.Panics(t, func() { require.NoError(t, app.ValidInit(nil, statePanic)) }) }) } @@ -99,7 +100,7 @@ func MockActionAppTest(t *testing.T, app MockApp) { t.Run("InitState", func(t *testing.T) { _, _, err := app.InitState(nil, []Action{actValid}) // Sadly we can not check Allocation.valid() here, since it is private. - assert.NoError(t, err) + require.NoError(t, err) _, _, err = app.InitState(nil, []Action{actErr}) assert.Error(t, err) @@ -114,7 +115,7 @@ func MockActionAppTest(t *testing.T, app MockApp) { }) t.Run("ValidAction", func(t *testing.T) { - assert.NoError(t, app.ValidAction(nil, nil, 0, actValid)) + require.NoError(t, app.ValidAction(nil, nil, 0, actValid)) assert.Error(t, app.ValidAction(nil, nil, 0, actErr)) assert.True(t, IsStateTransitionError(app.ValidAction(nil, nil, 0, actTransErr))) assert.True(t, IsActionError(app.ValidAction(nil, nil, 0, actActErr))) @@ -125,7 +126,7 @@ func MockActionAppTest(t *testing.T, app MockApp) { // ApplyActions increments the Version counter, so we cant pass nil as state. retState, err := app.ApplyActions(nil, state, []Action{actValid}) assert.Equal(t, retState.Version, state.Version+1) - assert.NoError(t, err) + require.NoError(t, err) _, err = app.ApplyActions(nil, state, []Action{actErr}) assert.Error(t, err) diff --git a/channel/multi/adjudicator.go b/channel/multi/adjudicator.go index 60fe2512f..80c9467bc 100644 --- a/channel/multi/adjudicator.go +++ b/channel/multi/adjudicator.go @@ -112,7 +112,7 @@ func (a *Adjudicator) dispatch(assetIds []LedgerBackendID, f func(channel.Adjudi }(l) } - for i := 0; i < n; i++ { + for range n { err := <-errs if err != nil { return err diff --git a/channel/multi/funder.go b/channel/multi/funder.go index 455ea182d..e18048c6a 100644 --- a/channel/multi/funder.go +++ b/channel/multi/funder.go @@ -17,6 +17,7 @@ package multi import ( "context" "fmt" + "math" "time" "perun.network/go-perun/channel" @@ -63,7 +64,11 @@ func (f *Funder) SetEgoisticPart(index int) { // channel. If any of the funder calls fails, the method returns an error. func (f *Funder) Fund(ctx context.Context, request channel.FundingReq) error { // Define funding timeout. - d := time.Duration(request.Params.ChallengeDuration) * time.Second + duration := request.Params.ChallengeDuration + if duration > math.MaxInt64 { + return fmt.Errorf("challenge duration %d is too large", duration) + } + d := time.Duration(duration) * time.Second ctx, cancel := context.WithTimeout(ctx, d) defer cancel() @@ -122,7 +127,7 @@ func fundLedgers(ctx context.Context, request channel.FundingReq, assetIDs []Led } // Collect errors - for i := 0; i < n; i++ { + for range n { err := <-errs if err != nil { return err diff --git a/channel/multi/subscription.go b/channel/multi/subscription.go index fa801aa1a..2e90df0c9 100644 --- a/channel/multi/subscription.go +++ b/channel/multi/subscription.go @@ -75,7 +75,7 @@ func (s *AdjudicatorSubscription) Next() channel.AdjudicatorEvent { // Err blocks until an error occurred and returns it. func (s *AdjudicatorSubscription) Err() error { - for i := 0; i < len(s.subs); i++ { + for range len(s.subs) { err := <-s.errors if err != nil { return err diff --git a/channel/params.go b/channel/params.go index 4281088d9..58b170b53 100644 --- a/channel/params.go +++ b/channel/params.go @@ -39,6 +39,17 @@ const MinNumParts = 2 // Nonce is the channel parameters' nonce type. type Nonce = *big.Int +// AuxMaxLen is the maximum byte count of the auxiliary data. +const AuxMaxLen = 256 + +// Aux is the channel parameters' auxiliary data type. +type Aux = [AuxMaxLen]byte + +// ConvertIDToBytes converts an ID to a []byte slice. +func ConvertIDToBytes(id ID) []byte { + return id[:] +} + // NonceFromBytes creates a nonce from a byte slice. func NonceFromBytes(b []byte) Nonce { if len(b) > MaxNonceLen { @@ -50,6 +61,8 @@ func NonceFromBytes(b []byte) Nonce { // Zero is the default channelID. var Zero = ID{} +var ZeroAux = Aux{} + var _ perunio.Serializer = (*Params)(nil) // Params are a channel's immutable parameters. A channel's id is the hash of @@ -72,18 +85,15 @@ type Params struct { LedgerChannel bool // VirtualChannel specifies whether this is a virtual channel. VirtualChannel bool -} - -// ID returns the channelID of this channel. -func (p *Params) ID() ID { - return p.id + // Aux is an optional field that can be used to store additional information. + Aux Aux } // NewParams creates Params from the given data and performs sanity checks. The // appDef optional: if it is nil, it describes a payment channel. The channel id // is also calculated here and persisted because it probably is an expensive // hash operation. -func NewParams(challengeDuration uint64, parts []map[wallet.BackendID]wallet.Address, app App, nonce Nonce, ledger bool, virtual bool) (*Params, error) { +func NewParams(challengeDuration uint64, parts []map[wallet.BackendID]wallet.Address, app App, nonce Nonce, ledger bool, virtual bool, aux Aux) (*Params, error) { if err := ValidateParameters(challengeDuration, len(parts), app, nonce); err != nil { return nil, errors.WithMessage(err, "invalid parameter for NewParams") } @@ -97,7 +107,35 @@ func NewParams(challengeDuration uint64, parts []map[wallet.BackendID]wallet.Add } } } - return NewParamsUnsafe(challengeDuration, parts, app, nonce, ledger, virtual), nil + return NewParamsUnsafe(challengeDuration, parts, app, nonce, ledger, virtual, aux), nil +} + +// NewParamsUnsafe creates Params from the given data and does NOT perform +// sanity checks. The channel id is also calculated here and persisted because +// it probably is an expensive hash operation. +func NewParamsUnsafe(challengeDuration uint64, parts []map[wallet.BackendID]wallet.Address, app App, nonce Nonce, ledger bool, virtual bool, aux Aux) *Params { + p := &Params{ + ChallengeDuration: challengeDuration, + Parts: parts, + App: app, + Nonce: nonce, + LedgerChannel: ledger, + VirtualChannel: virtual, + Aux: aux, + } + + // probably an expensive hash operation, do it only once during creation. + id, err := CalcID(p) + if err != nil || id == Zero { + log.Panicf("Could not calculate channel id: %v", err) + } + p.id = id + return p +} + +// ID returns the channelID of this channel. +func (p *Params) ID() ID { + return p.id } // ValidateProposalParameters validates all parameters that are part of the @@ -136,28 +174,6 @@ func ValidateParameters(challengeDuration uint64, numParts int, app App, nonce N return nil } -// NewParamsUnsafe creates Params from the given data and does NOT perform -// sanity checks. The channel id is also calculated here and persisted because -// it probably is an expensive hash operation. -func NewParamsUnsafe(challengeDuration uint64, parts []map[wallet.BackendID]wallet.Address, app App, nonce Nonce, ledger bool, virtual bool) *Params { - p := &Params{ - ChallengeDuration: challengeDuration, - Parts: parts, - App: app, - Nonce: nonce, - LedgerChannel: ledger, - VirtualChannel: virtual, - } - - // probably an expensive hash operation, do it only once during creation. - id, err := CalcID(p) - if err != nil || id == Zero { - log.Panicf("Could not calculate channel id: %v", err) - } - p.id = id - return p -} - // CloneAddresses returns a clone of an Address using its binary marshaling // implementation. It panics if an error occurs during binary (un)marshaling. func CloneAddresses(as []map[wallet.BackendID]wallet.Address) []map[wallet.BackendID]wallet.Address { @@ -178,6 +194,7 @@ func (p *Params) Clone() *Params { Nonce: new(big.Int).Set(p.Nonce), LedgerChannel: p.LedgerChannel, VirtualChannel: p.VirtualChannel, + Aux: p.Aux, } } @@ -190,6 +207,7 @@ func (p *Params) Encode(w stdio.Writer) error { p.Nonce, p.LedgerChannel, p.VirtualChannel, + p.Aux, ) } @@ -202,6 +220,7 @@ func (p *Params) Decode(r stdio.Reader) error { nonce Nonce ledger bool virtual bool + aux Aux ) err := perunio.Decode(r, @@ -211,12 +230,13 @@ func (p *Params) Decode(r stdio.Reader) error { &nonce, &ledger, &virtual, + &aux, ) if err != nil { return err } - _p, err := NewParams(challengeDuration, parts.Addr, app, nonce, ledger, virtual) + _p, err := NewParams(challengeDuration, parts.Addr, app, nonce, ledger, virtual, aux) if err != nil { return err } diff --git a/channel/persistence/keyvalue/cache.go b/channel/persistence/keyvalue/cache.go index 5b0ad8cf1..cdd75da67 100644 --- a/channel/persistence/keyvalue/cache.go +++ b/channel/persistence/keyvalue/cache.go @@ -22,7 +22,7 @@ import ( "perun.network/go-perun/wire" ) -//nolint:deadcode +//nolint:unused func newChannelCache() *channelCache { return &channelCache{ peers: make(map[channel.ID][]wire.Address), @@ -31,12 +31,15 @@ func newChannelCache() *channelCache { } // channelCache contains all channels. +// +//nolint:unused type channelCache struct { mutex stdsync.RWMutex peers map[channel.ID][]wire.Address // Used when closing a channel. peerChannels map[string]map[channel.ID]struct{} // Address -> Set } +//nolint:unused func (c *channelCache) addPeerChannel(addr wire.Address, chID channel.ID) { c.mutex.Lock() defer c.mutex.Unlock() @@ -56,6 +59,7 @@ func (c *channelCache) addPeerChannel(addr wire.Address, chID channel.ID) { } } +//nolint:unused func (c *channelCache) deleteChannel(id channel.ID) []wire.Address { c.mutex.Lock() defer c.mutex.Unlock() @@ -78,6 +82,7 @@ func (c *channelCache) deleteChannel(id channel.ID) []wire.Address { return peers } +//nolint:unused func (c *channelCache) clear() { c.mutex.Lock() defer c.mutex.Unlock() diff --git a/channel/persistence/keyvalue/persistrestorer.go b/channel/persistence/keyvalue/persistrestorer.go index 9e2b94be3..9a3ecee22 100644 --- a/channel/persistence/keyvalue/persistrestorer.go +++ b/channel/persistence/keyvalue/persistrestorer.go @@ -27,6 +27,13 @@ type PersistRestorer struct { db sortedkv.Database } +// NewPersistRestorer creates a new PersistRestorer for the supplied database. +func NewPersistRestorer(db sortedkv.Database) *PersistRestorer { + return &PersistRestorer{ + db: db, + } +} + // Close closes the PersistRestorer and releases all resources it holds. func (pr *PersistRestorer) Close() error { if err := pr.db.Close(); err != nil { @@ -35,13 +42,6 @@ func (pr *PersistRestorer) Close() error { return nil } -// NewPersistRestorer creates a new PersistRestorer for the supplied database. -func NewPersistRestorer(db sortedkv.Database) *PersistRestorer { - return &PersistRestorer{ - db: db, - } -} - var prefix = struct{ ChannelDB, PeerDB, SigKey, Peers string }{ ChannelDB: "Chan:", PeerDB: "Peer:", diff --git a/channel/persistence/keyvalue/persistrestorer_internal_test.go b/channel/persistence/keyvalue/persistrestorer_internal_test.go index de878154a..604ebec76 100644 --- a/channel/persistence/keyvalue/persistrestorer_internal_test.go +++ b/channel/persistence/keyvalue/persistrestorer_internal_test.go @@ -16,7 +16,6 @@ package keyvalue import ( "context" - "os" "testing" "github.com/stretchr/testify/assert" @@ -31,8 +30,7 @@ import ( ) func TestPersistRestorer_Generic(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "perun-test-kvpersistrestorer-db-*") - require.NoError(t, err) + tmpdir := t.TempDir() lvldb, err := leveldb.LoadDatabase(tmpdir) require.NoError(t, err) @@ -62,5 +60,5 @@ func TestChannelIterator_Next_Empty(t *testing.T) { var success bool assert.NotPanics(t, func() { success = it.Next(context.Background()) }) assert.False(t, success) - assert.NoError(t, it.err) + require.NoError(t, it.err) } diff --git a/channel/persistence/keyvalue/restorer.go b/channel/persistence/keyvalue/restorer.go index bfb949768..5139eabac 100644 --- a/channel/persistence/keyvalue/restorer.go +++ b/channel/persistence/keyvalue/restorer.go @@ -69,7 +69,7 @@ func (pr *PersistRestorer) channelPeers(id channel.ID) ([]map[wallet.BackendID]w if err != nil { return nil, errors.WithMessage(err, "unable to get peerlist from db") } - return ps, errors.WithMessage(perunio.Decode(bytes.NewBuffer([]byte(peers)), &ps), + return ps, errors.WithMessage(perunio.Decode(bytes.NewBufferString(peers), &ps), "decoding peerlist") } @@ -169,6 +169,24 @@ func (i *ChannelIterator) Next(context.Context) bool { return i.decodeNext("staging:state", &PersistedState{&i.ch.StagingTXV.State}, allowEmpty) } +// Channel returns the iterator's current channel. +func (i *ChannelIterator) Channel() *persistence.Channel { + return i.ch +} + +// Close closes the iterator and releases its resources. It returns the last +// error that occurred when advancing the iterator. +func (i *ChannelIterator) Close() error { + for it := range i.its { + if err := i.its[it].Close(); err != nil && i.err == nil { + i.err = err + } + } + i.its = nil + + return i.err +} + // recoverFromEmptyIterator is called when there is no iterator or when the // current iterator just ended. allowEnd signifies whether this situation is // allowed. It returns whether it could recover a new iterator. @@ -217,21 +235,3 @@ func (i *ChannelIterator) decodeNext(key string, v interface{}, opts decOpts) bo return i.err == nil } - -// Channel returns the iterator's current channel. -func (i *ChannelIterator) Channel() *persistence.Channel { - return i.ch -} - -// Close closes the iterator and releases its resources. It returns the last -// error that occurred when advancing the iterator. -func (i *ChannelIterator) Close() error { - for it := range i.its { - if err := i.its[it].Close(); err != nil && i.err == nil { - i.err = err - } - } - i.its = nil - - return i.err -} diff --git a/channel/persistence/statemachine_test.go b/channel/persistence/statemachine_test.go index cb675ba70..c5b812bdc 100644 --- a/channel/persistence/statemachine_test.go +++ b/channel/persistence/statemachine_test.go @@ -76,7 +76,7 @@ func TestStateMachine(t *testing.T) { sig, err = channel.Sign(acc, csm.StagingState(), b) require.NoError(err) } - err = sm.AddSig(ctx, channel.Index(i), sig) + err = sm.AddSig(ctx, channel.Index(i), sig) //nolint:gosec require.NoError(err) tpr.AssertEqual(csm) } @@ -152,7 +152,7 @@ func TestStateMachine(t *testing.T) { // Set Progressed timeout := ctest.NewRandomTimeout(rng) - idx := channel.Index(rng.Intn(s.NumParts())) + idx := channel.Index(rng.Intn(s.NumParts())) //nolint:gosec e := channel.NewProgressedEvent(s.ID, timeout, s, idx) err = sm.SetProgressed(ctx, e) require.NoError(err) diff --git a/channel/persistence/test/channel.go b/channel/persistence/test/channel.go index 75638edef..26c8e3f79 100644 --- a/channel/persistence/test/channel.go +++ b/channel/persistence/test/channel.go @@ -18,6 +18,7 @@ import ( "context" "math/rand" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "perun.network/go-perun/channel" @@ -89,7 +90,7 @@ func NewRandomChannel( } func requireEqualPeers(t require.TestingT, expected, actual []map[wallet.BackendID]wire.Address) { - require.Equal(t, len(expected), len(actual)) + assert.Equal(t, len(expected), len(actual)) for i, p := range expected { if !channel.EqualWireMaps(p, actual[i]) { t.Errorf("restored peers for channel do not match\nexpected: %v\nactual: %v", @@ -106,10 +107,10 @@ func requireEqualPeers(t require.TestingT, expected, actual []map[wallet.Backend func (c *Channel) AssertPersisted(ctx context.Context, t require.TestingT) { ch, err := c.pr.RestoreChannel(ctx, c.ID()) require.NoError(t, err) - require.NotNil(t, ch) + assert.NotNil(t, ch) c.RequireEqual(t, ch) requireEqualPeers(t, c.peers, ch.PeersV) - require.Equal(t, c.parent, ch.Parent) + assert.Equal(t, c.parent, ch.Parent) } // RequireEqual asserts that the channel is equal to the provided channel state. @@ -182,7 +183,7 @@ func (c *Channel) SignAll(ctx context.Context, t require.TestingT) { for i := range c.accounts { sig, err := channel.Sign(c.accounts[i][channel.TestBackendID], c.StagingState(), channel.TestBackendID) require.NoError(t, err) - c.AddSig(ctx, channel.Index(i), sig) //nolint:errcheck + c.AddSig(ctx, channel.Index(i), sig) //nolint:errcheck, gosec c.AssertPersisted(ctx, t) } } @@ -232,14 +233,14 @@ func (c *Channel) SetRegistered(t require.TestingT) { // SetWithdrawing calls SetWithdrawing on the state machine and then checks the persistence. func (c *Channel) SetWithdrawing(t require.TestingT) { - require.NoError(t, c.StateMachine.SetWithdrawing(c.ctx)) + assert.NoError(t, c.StateMachine.SetWithdrawing(c.ctx)) c.AssertPersisted(c.ctx, t) } // SetWithdrawn calls SetWithdrawn on the state machine and then checks the persistence. func (c *Channel) SetWithdrawn(t require.TestingT) { - require.NoError(t, c.StateMachine.SetWithdrawn(c.ctx)) + assert.NoError(t, c.StateMachine.SetWithdrawn(c.ctx)) rc, err := c.pr.RestoreChannel(c.ctx, c.ID()) - require.Error(t, err, "restoring of a non-existing channel") - require.Nil(t, rc, "restoring of a non-existing channel") + assert.Error(t, err, "restoring of a non-existing channel") + assert.Nil(t, rc, "restoring of a non-existing channel") } diff --git a/channel/persistence/test/channel_internal_test.go b/channel/persistence/test/channel_internal_test.go index 56a10e348..fe25b9e70 100644 --- a/channel/persistence/test/channel_internal_test.go +++ b/channel/persistence/test/channel_internal_test.go @@ -59,7 +59,7 @@ func initSigSlice(length int, prng *rand.Rand) []wallet.Sig { s := make([]wallet.Sig, length) for i := range s { s[i] = make(wallet.Sig, 32) - for j := 0; j < 32; j++ { + for j := range 32 { s[i][j] = byte(prng.Int()) } } diff --git a/channel/persistence/test/peerchans.go b/channel/persistence/test/peerchans.go index 58de9d738..6377f4d2c 100644 --- a/channel/persistence/test/peerchans.go +++ b/channel/persistence/test/peerchans.go @@ -51,13 +51,6 @@ func (pc peerChans) Add(id channel.ID, ps ...map[wallet.BackendID]wire.Address) } } -// Don't use add, use Add. -func (pc peerChans) add(id channel.ID, p map[wallet.BackendID]wire.Address) { - pk := peerKey(p) - ids := pc[pk] // nil ok, since we append - pc[pk] = append(ids, id) -} - func (pc peerChans) Delete(id channel.ID) { for pk, ids := range pc { for i, pid := range ids { @@ -78,6 +71,13 @@ func (pc peerChans) Delete(id channel.ID) { } } +// Don't use add, use Add. +func (pc peerChans) add(id channel.ID, p map[wallet.BackendID]wire.Address) { + pk := peerKey(p) + ids := pc[pk] // nil ok, since we append + pc[pk] = append(ids, id) +} + func peerKey(a map[wallet.BackendID]wire.Address) string { key := new(bytes.Buffer) err := perunio.Encode(key, wire.AddressDecMap(a)) @@ -90,7 +90,7 @@ func peerKey(a map[wallet.BackendID]wire.Address) string { func peerFromKey(s string) (map[wallet.BackendID]wire.Address, error) { p := make(map[wallet.BackendID]wire.Address) decMap := wire.AddressDecMap(p) - err := perunio.Decode(bytes.NewBuffer([]byte(s)), &decMap) + err := perunio.Decode(bytes.NewBufferString(s), &decMap) if err != nil { return nil, fmt.Errorf("error decoding peer key: %w", err) } diff --git a/channel/persistence/test/persistrestorer.go b/channel/persistence/test/persistrestorer.go index 81f23360a..775462d13 100644 --- a/channel/persistence/test/persistrestorer.go +++ b/channel/persistence/test/persistrestorer.go @@ -170,17 +170,6 @@ func (pr *PersistRestorer) AssertNotExists(id channel.ID) { assert.Falsef(pr.t, ok, "channel shouldn't exist: %x", id) } -// channel is a mutexed access to the Channel stored at the given id. -// Since persister access is guaranteed to be single-threaded per channel, it -// makes sense for the Persister implementation methods to use this getter to -// channel the pointer to the channel storage. -func (pr *PersistRestorer) channel(id channel.ID) (*persistence.Channel, bool) { - pr.mu.Lock() - defer pr.mu.Unlock() - ch, ok := pr.chans[id] - return ch, ok -} - // Restorer implementation // ActivePeers returns all peers that channels are persisted for. @@ -239,3 +228,14 @@ func (i *chanIter) Close() error { i.chans = nil // GC return nil } + +// channel is a mutexed access to the Channel stored at the given id. +// Since persister access is guaranteed to be single-threaded per channel, it +// makes sense for the Persister implementation methods to use this getter to +// channel the pointer to the channel storage. +func (pr *PersistRestorer) channel(id channel.ID) (*persistence.Channel, bool) { + pr.mu.Lock() + defer pr.mu.Unlock() + ch, ok := pr.chans[id] + return ch, ok +} diff --git a/channel/persistence/test/persistrestorertest.go b/channel/persistence/test/persistrestorertest.go index ffbe252a6..01e4ccd15 100644 --- a/channel/persistence/test/persistrestorertest.go +++ b/channel/persistence/test/persistrestorertest.go @@ -67,7 +67,7 @@ func (c *Client) NewChannel(t require.TestingT, p map[wallet.BackendID]wire.Addr c.ctx, t, c.pr, - channel.Index(idx), + channel.Index(idx), //nolint:gosec peers, parent, c.rng) @@ -89,7 +89,7 @@ func GenericPersistRestorerTest( t.Helper() t.Run("RestoreChannel error", func(t *testing.T) { var id channel.ID - ch, err := pr.RestoreChannel(context.Background(), id) + ch, err := pr.RestoreChannel(ctx, id) assert.Error(t, err) assert.Nil(t, ch) }) @@ -100,9 +100,9 @@ func GenericPersistRestorerTest( channels := make([]map[channel.ID]*Channel, numPeers) var prevCh *Channel - for p := 0; p < numPeers; p++ { + for p := range numPeers { channels[p] = make(map[channel.ID]*Channel) - for i := 0; i < numChans; i++ { + for i := range numChans { var parent *Channel // Every second channel is set to have a parent. if i&1 == 1 { @@ -118,9 +118,7 @@ func GenericPersistRestorerTest( subSeed := rng.Int63() iterIdx := 0 for idx := range peers { - idx := idx for _, ch := range channels[idx] { - ch := ch iterIdx++ iterIdx := iterIdx go ct.StageN("testing", numChans*numPeers, func(t pkgtest.ConcT) { @@ -198,5 +196,5 @@ peerLoop: ps, err := pr.ActivePeers(ctx) require.NoError(t, err) - require.Len(t, ps, 0) + require.Empty(t, ps) } diff --git a/channel/state.go b/channel/state.go index 9216b0066..ec5397303 100644 --- a/channel/state.go +++ b/channel/state.go @@ -159,7 +159,7 @@ func (s *State) Equal(t *State) error { // ToSubAlloc creates a SubAlloc from the state that can be added to the // parent channel's locked funds. func (s *State) ToSubAlloc() *SubAlloc { - return NewSubAlloc(s.ID, s.Allocation.Sum(), nil) + return NewSubAlloc(s.ID, s.Sum(), nil) } // EqualWireMaps compares two wire.Address maps for equality. diff --git a/channel/statemachine.go b/channel/statemachine.go index 2508b3475..57352b77a 100644 --- a/channel/statemachine.go +++ b/channel/statemachine.go @@ -125,6 +125,14 @@ func (m *StateMachine) CheckUpdate( return nil } +// Clone returns a deep copy of StateMachine. +func (m *StateMachine) Clone() *StateMachine { + return &StateMachine{ + machine: m.machine.Clone(), + app: m.app, + } +} + // validTransition makes all the default transition checks and additionally // checks for a valid application specific transition. // This is where a StateMachine and ActionMachine differ. In an ActionMachine, @@ -135,7 +143,7 @@ func (m *StateMachine) validTransition(to *State, actor Index) (err error) { if actor >= m.N() { return errors.New("actor index is out of range") } - if err := m.machine.ValidTransition(to); err != nil { + if err := m.ValidTransition(to); err != nil { return err } @@ -144,11 +152,3 @@ func (m *StateMachine) validTransition(to *State, actor Index) (err error) { } return errors.WithMessagef(err, "runtime error in application's ValidTransition()") } - -// Clone returns a deep copy of StateMachine. -func (m *StateMachine) Clone() *StateMachine { - return &StateMachine{ - machine: m.machine.Clone(), - app: m.app, - } -} diff --git a/channel/test/app_randomizer_internal_test.go b/channel/test/app_randomizer_internal_test.go index 3416841a2..67e28d253 100644 --- a/channel/test/app_randomizer_internal_test.go +++ b/channel/test/app_randomizer_internal_test.go @@ -32,11 +32,11 @@ func TestAppRandomizerSet(t *testing.T) { assert.NotPanics(t, func() { SetAppRandomizer(NewMockAppRandomizer()) }, "first SetAppRandomizer() should work") assert.True(t, isAppRandomizerSet, "isAppRandomizerSet should be true") assert.NotNil(t, appRandomizer, "appRandomizer should not be nil") - assert.False(t, old == appRandomizer, "appRandomizer should have changed") + assert.NotEqual(t, old, appRandomizer, "appRandomizer should have changed") old = appRandomizer assert.Panics(t, func() { SetAppRandomizer(NewMockAppRandomizer()) }, "second SetAppRandomizer() should panic") assert.True(t, isAppRandomizerSet, "isAppRandomizerSet should be true") assert.NotNil(t, appRandomizer, "appRandomizer should not be nil") - assert.True(t, old == appRandomizer, "appRandomizer should not have changed") + assert.Equal(t, old, appRandomizer, "appRandomizer should not have changed") } diff --git a/channel/test/backend.go b/channel/test/backend.go index 2138d9f2f..11c0903c8 100644 --- a/channel/test/backend.go +++ b/channel/test/backend.go @@ -97,7 +97,7 @@ func genericChannelIDTest(t *testing.T, s *Setup) { t.Helper() require.NotNil(t, s.Params.Parts, "params.Parts can not be nil") _, err := channel.CalcID(s.Params) - assert.NoError(t, err, "CalcID should not return an error") + require.NoError(t, err, "CalcID should not return an error") // Check that modifying the state changes the id for _, modParams := range buildModifiedParams(s.Params, s.Params2, s) { @@ -110,7 +110,7 @@ func genericChannelIDTest(t *testing.T, s *Setup) { func genericSignTest(t *testing.T, s *Setup) { t.Helper() _, err := channel.Sign(s.Account, s.State, s.State.Backends[0]) - assert.NoError(t, err, "Sign should not return an error") + require.NoError(t, err, "Sign should not return an error") } func genericVerifyTest(t *testing.T, s *Setup, opts ...GenericTestOption) { @@ -123,22 +123,22 @@ func genericVerifyTest(t *testing.T, s *Setup, opts ...GenericTestOption) { require.NoError(t, err, "Sign should not return an error") ok, err := channel.Verify(addr, s.State, sig) - assert.NoError(t, err, "Verify should not return an error") + require.NoError(t, err, "Verify should not return an error") assert.True(t, ok, "Verify should return true") for i, _modState := range buildModifiedStates(s.State, s.State2, append(opts, IgnoreApp)...) { modState := _modState ok, err = channel.Verify(addr, &modState, sig) assert.Falsef(t, ok, "Verify should return false: index %d", i) - assert.NoError(t, err, "Verify should not return an error") + require.NoError(t, err, "Verify should not return an error") } // Different address and same state and params - for i := 0; i < 10; i++ { + for range 10 { add := s.RandomAddress() for _, a := range add { ok, err := channel.Verify(a, s.State, sig) - assert.NoError(t, err, "Verify should not return an error") + require.NoError(t, err, "Verify should not return an error") assert.False(t, ok, "Verify should return false") } } @@ -196,6 +196,7 @@ func appendModParams(a []channel.Params, modParams channel.Params) []channel.Par modParams.Nonce, modParams.LedgerChannel, modParams.VirtualChannel, + modParams.Aux, ) return append(a, *p) } @@ -252,8 +253,8 @@ func buildModifiedStates(s1, s2 *channel.State, _opts ...GenericTestOption) (ret // Modify Assets[0] { modState := s1.Clone() - modState.Allocation.Assets[0] = s2.Allocation.Assets[0] - modState.Allocation.Backends[0] = s2.Allocation.Backends[0] + modState.Assets[0] = s2.Assets[0] + modState.Backends[0] = s2.Backends[0] ret = append(ret, *modState) } } @@ -269,14 +270,14 @@ func buildModifiedStates(s1, s2 *channel.State, _opts ...GenericTestOption) (ret // Modify Balances[0] { modState := s1.Clone() - modState.Allocation.Balances[0] = s2.Allocation.Balances[0] + modState.Balances[0] = s2.Balances[0] modState = ensureConsistentBalances(modState) ret = append(ret, *modState) } // Modify Balances[0][0] { modState := s1.Clone() - modState.Allocation.Balances[0][0] = s2.Allocation.Balances[0][0] + modState.Balances[0][0] = s2.Balances[0][0] ret = append(ret, *modState) } } @@ -285,7 +286,7 @@ func buildModifiedStates(s1, s2 *channel.State, _opts ...GenericTestOption) (ret // Modify complete Locked { modState := s1.Clone() - modState.Allocation.Locked = s2.Clone().Locked + modState.Locked = s2.Clone().Locked modState = ensureConsistentBalances(modState) ret = append(ret, *modState) } @@ -370,8 +371,8 @@ func ensureBalanceVectorLength(bals []channel.Bal, l int) []channel.Bal { // GenericStateEqualTest tests the State.Equal function. func GenericStateEqualTest(t *testing.T, s1, s2 *channel.State, opts ...GenericTestOption) { t.Helper() - assert.NoError(t, s1.Equal(s1)) //nolint:gocritic - assert.NoError(t, s2.Equal(s2)) //nolint:gocritic + require.NoError(t, s1.Equal(s1)) //nolint:gocritic + require.NoError(t, s2.Equal(s2)) //nolint:gocritic for _, differentState := range buildModifiedStates(s1, s2, opts...) { assert.Error(t, differentState.Equal(s1)) diff --git a/channel/test/randomizer.go b/channel/test/randomizer.go index 44c1657dc..510c61af2 100644 --- a/channel/test/randomizer.go +++ b/channel/test/randomizer.go @@ -18,6 +18,7 @@ import ( crand "crypto/rand" "fmt" "log" + "math" "math/big" "math/rand" "time" @@ -48,7 +49,11 @@ func SetRandomizer(r Randomizer, bID wallet.BackendID) { // NewRandomPhase generates a random channel machine phase. func NewRandomPhase(rng *rand.Rand) channel.Phase { - return channel.Phase(rng.Intn(channel.LastPhase + 1)) + phase := rng.Intn(channel.LastPhase + 1) + if phase < 0 || phase > math.MaxUint8 { + panic("LastPhase is too large") + } + return channel.Phase(phase) } // NewRandomAsset generates a new random `channel.Asset`. @@ -199,8 +204,9 @@ func NewRandomParams(rng *rand.Rand, opts ...RandomOpt) *channel.Params { app := NewRandomApp(rng, opt) ledger := opt.LedgerChannel(rng) virtual := opt.VirtualChannel(rng) + aux := opt.Aux(rng) - params := channel.NewParamsUnsafe(challengeDuration, parts, app, nonce, ledger, virtual) + params := channel.NewParamsUnsafe(challengeDuration, parts, app, nonce, ledger, virtual, aux) updateOpts(opts, WithParams(params)) return params } @@ -261,7 +267,11 @@ func NewRandomChannelIDs(rng *rand.Rand, n int) (ids []channel.ID) { func NewRandomIndexMap(rng *rand.Rand, numParts int, numPartsParent int) (m []channel.Index) { m = make([]channel.Index, numParts) for i := range m { - m[i] = channel.Index(rng.Intn(numPartsParent)) + idx := rng.Intn(numPartsParent) + if idx < 0 || idx >= math.MaxUint16 { + panic("index out of bounds") + } + m[i] = channel.Index(idx) } return } @@ -279,24 +289,25 @@ func NewRandomIndexMaps(rng *rand.Rand, numParts int, numPartsParent int) (maps // Options: `WithBalancesRange`. func NewRandomBal(rng *rand.Rand, opts ...RandomOpt) channel.Bal { opt := mergeRandomOpts(opts...) - min, max := opt.BalancesRange() - if min == nil { + var balanceMin, balanceMax channel.Bal + balanceMin, balanceMax = opt.BalancesRange() + if balanceMin == nil { // Use 1 here since 0 is nearly impossible anyway and many // test assume != 0. - min = big.NewInt(1) + balanceMin = big.NewInt(1) } - if max == nil { - max = maxRandomBalance + if balanceMax == nil { + balanceMax = maxRandomBalance } - // rng(max - min + 1) - bal, err := crand.Int(rng, new(big.Int).Add(new(big.Int).Sub(max, min), big.NewInt(1))) + // rng(balanceMax - balanceMin + 1) + bal, err := crand.Int(rng, new(big.Int).Add(new(big.Int).Sub(balanceMax, balanceMin), big.NewInt(1))) if err != nil { panic(fmt.Sprintf("Error creating random big.Int: %v", err)) } - // min + rng(max - min + 1) - return new(big.Int).Add(min, bal) + // balanceMin + rng(balanceMax - balanceMin + 1) + return new(big.Int).Add(balanceMin, bal) } // NewRandomBals generates new random `channel.Bal`s. @@ -393,7 +404,6 @@ func NewRandomTransaction(rng *rand.Rand, sigMask []bool, opts ...RandomOpt) *ch func ShuffleBalances(rng *rand.Rand, b channel.Balances) channel.Balances { ret := b.Clone() for _, a := range ret { - a := a rng.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] }) diff --git a/channel/test/randomopts.go b/channel/test/randomopts.go index dbf86112a..b20c75204 100644 --- a/channel/test/randomopts.go +++ b/channel/test/randomopts.go @@ -15,6 +15,7 @@ package test import ( + "errors" "fmt" "io" "math/big" @@ -29,10 +30,10 @@ var ( // It is set to 2 ^ 128 - 1 since when 2 ^ 256 - 1 is used, the faucet // key is depleted. // The production limit can be found in `go-perun/channel.MaxBalance`. - MaxBalance = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)) //nolint:gomnd + MaxBalance = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)) //nolint:mnd // Highest balance that is returned by NewRandomBal. Set to MaxBalance / 2^30. - maxRandomBalance = new(big.Int).Rsh(MaxBalance, 30) //nolint:gomnd + maxRandomBalance = new(big.Int).Rsh(MaxBalance, 30) //nolint:mnd ) const ( @@ -112,8 +113,8 @@ func WithBalances(balances ...[]channel.Bal) RandomOpt { } // WithBalancesInRange sets the range within which balances are randomly generated to [min, max]. -func WithBalancesInRange(min, max channel.Bal) RandomOpt { - return RandomOpt{"balanceRange": []channel.Bal{min, max}} +func WithBalancesInRange(balanceMin, balanceMax channel.Bal) RandomOpt { + return RandomOpt{"balanceRange": []channel.Bal{balanceMin, balanceMax}} } // WithChallengeDuration sets the `ChallengeDuration` that should be used. @@ -221,6 +222,11 @@ func WithVirtualChannel(b bool) RandomOpt { return RandomOpt{nameVirtualChannel: b} } +// WithAux sets the `Aux` attribute. +func WithAux(aux channel.Aux) RandomOpt { + return RandomOpt{"aux": aux} +} + // Append inserts all `opts` into the receiving object and returns the result. // Overrides entries that occur more than once with the last occurrence. func (o RandomOpt) Append(opts ...RandomOpt) RandomOpt { @@ -304,7 +310,7 @@ func (o RandomOpt) Assets() []channel.Asset { // Backend returns the `Backend` value of the `RandomOpt`. func (o RandomOpt) Backend() (wallet.BackendID, error) { if _, ok := o["backend"]; !ok { - return 0, fmt.Errorf("backend not set") + return 0, errors.New("backend not set") } return o["backend"].(wallet.BackendID), nil } @@ -312,7 +318,7 @@ func (o RandomOpt) Backend() (wallet.BackendID, error) { // BackendID returns the `BackendID` value from `Allocation` of the `RandomOpt`. func (o RandomOpt) BackendID() ([]wallet.BackendID, error) { if _, ok := o["backendIDs"]; !ok { - return []wallet.BackendID{0}, fmt.Errorf("backend not set") + return []wallet.BackendID{0}, errors.New("backend not set") } return o["backendIDs"].([]wallet.BackendID), nil } @@ -328,7 +334,7 @@ func (o RandomOpt) Balances() channel.Balances { // BalancesRange returns the `BalancesRange` value of the `RandomOpt`. // If not present, returns nil,nil. -func (o RandomOpt) BalancesRange() (min, max channel.Bal) { +func (o RandomOpt) BalancesRange() (balanceMin, balanceMax channel.Bal) { if _, ok := o["balanceRange"]; !ok { return nil, nil } @@ -367,7 +373,7 @@ func (o RandomOpt) FirstPart() map[wallet.BackendID]wallet.Address { // If not present, a random value is generated with `rng` as entropy source. func (o RandomOpt) IsFinal(rng *rand.Rand) bool { if _, ok := o["isFinal"]; !ok { - o["isFinal"] = (rng.Int31n(2) == 0) //nolint:gomnd + o["isFinal"] = (rng.Int31n(2) == 0) //nolint:mnd } return o["isFinal"].(bool) } @@ -430,7 +436,7 @@ func (o RandomOpt) LedgerChannel(rng io.Reader) bool { if err != nil { panic(err) } - o[nameLedgerChannel] = a[0]%2 == 0 //nolint:gomnd + o[nameLedgerChannel] = a[0]%2 == 0 //nolint:mnd } return o[nameLedgerChannel].(bool) } @@ -444,11 +450,25 @@ func (o RandomOpt) VirtualChannel(rng io.Reader) bool { if err != nil { panic(err) } - o[nameVirtualChannel] = a[0]%2 == 0 //nolint:gomnd + o[nameVirtualChannel] = a[0]%2 == 0 //nolint:mnd } return o[nameVirtualChannel].(bool) } +// Aux returns the `Aux` value of the `RandomOpt`. +// If not present, a random value is generated with `rng` as entropy source. +func (o RandomOpt) Aux(rng io.Reader) channel.Aux { + if _, ok := o["aux"]; !ok { + a := make([]byte, channel.AuxMaxLen) + _, err := rng.Read(a) + if err != nil { + panic(err) + } + o["aux"] = channel.Aux(a) + } + return o["aux"].(channel.Aux) +} + // NumAssets returns the `NumAssets` value of the `RandomOpt`. // If not present, a random value is generated with `rng` as entropy source. func (o RandomOpt) NumAssets(rng *rand.Rand) int { diff --git a/channel/transaction.go b/channel/transaction.go index 1539d2f86..e616ac859 100644 --- a/channel/transaction.go +++ b/channel/transaction.go @@ -76,7 +76,7 @@ func (t *Transaction) Decode(r io.Reader) error { return errors.WithMessage(err, "decoding state") } - t.Sigs = make([]wallet.Sig, t.State.NumParts()) + t.Sigs = make([]wallet.Sig, t.NumParts()) return wallet.DecodeSparseSigs(r, &t.Sigs) } diff --git a/channel/transaction_test.go b/channel/transaction_test.go index 70d2a2726..63fde0062 100644 --- a/channel/transaction_test.go +++ b/channel/transaction_test.go @@ -33,7 +33,7 @@ func TestTransactionSerialization(t *testing.T) { tests = append(tests, newUniformBoolSlice(l, true), newUniformBoolSlice(l, false), newStripedBoolSlice(l, true), newStripedBoolSlice(l, false)) - for i := 0; i < l; i++ { + for i := range l { tests = append(tests, newAlmostUniformBoolSlice(i, l, true)) tests = append(tests, newAlmostUniformBoolSlice(i, l, false)) } diff --git a/client/adjudicate.go b/client/adjudicate.go index d1b9c6fc2..9179db73c 100644 --- a/client/adjudicate.go +++ b/client/adjudicate.go @@ -442,7 +442,11 @@ func (c *Channel) gatherSubChannelStates() (states []channel.SignedState, err er func (c *Channel) subChannelStateMap() (states channel.StateMap, err error) { states = channel.MakeStateMap() err = c.applyToSubChannelsRecursive(func(c *Channel) error { - states[c.ID()] = c.state() + states[c.ID()] = &channel.SignedState{ + Params: c.Params(), + State: c.machine.CurrentTX().State, + Sigs: c.machine.CurrentTX().Sigs, + } return nil }) return diff --git a/client/channel.go b/client/channel.go index 72e107052..ada79e101 100644 --- a/client/channel.go +++ b/client/channel.go @@ -127,10 +127,6 @@ func (c *Channel) Ctx() context.Context { return c.conn.r.Ctx() } -func (c *Channel) logPeer(idx channel.Index) log.Logger { - return c.Log().WithField("peerIdx", idx) -} - // ID returns the channel ID. func (c *Channel) ID() channel.ID { return c.machine.ID() @@ -156,13 +152,6 @@ func (c *Channel) State() *channel.State { return c.state() } -// state returns a pointer to the current state. -// Assumes that the machine mutex has been locked. -// Clone the state if you want to modify it. -func (c *Channel) state() *channel.State { - return c.machine.State() -} - // Phase returns the current phase of the channel state machine. // Can not be called from an update handler. func (c *Channel) Phase() channel.Phase { @@ -244,3 +233,14 @@ func (c *Channel) initExchangeSigsAndEnable(ctx context.Context) error { func (c *Channel) hasLockedFunds() bool { return len(c.machine.State().Locked) > 0 } + +// state returns a pointer to the current state. +// Assumes that the machine mutex has been locked. +// Clone the state if you want to modify it. +func (c *Channel) state() *channel.State { + return c.machine.State() +} + +func (c *Channel) logPeer(idx channel.Index) log.Logger { + return c.Log().WithField("peerIdx", idx) +} diff --git a/client/channelconn.go b/client/channelconn.go index bbde16335..ffc099b25 100644 --- a/client/channelconn.go +++ b/client/channelconn.go @@ -16,6 +16,7 @@ package client import ( "context" + "math" "github.com/pkg/errors" "golang.org/x/sync/errgroup" @@ -41,6 +42,57 @@ type channelConn struct { log log.Logger } +// Send broadcasts the message to all channel participants. +func (c *channelConn) Send(ctx context.Context, msg wire.Msg) error { + var eg errgroup.Group + for i, peer := range c.peers { + if i < 0 || i > math.MaxUint16 { + return errors.Errorf("channel connection peer index out of bounds: %d", i) + } + if channel.Index(i) == c.idx { + continue // skip own peer + } + c.log.WithField("peer", peer).Debugf("channelConn: publishing message: %v: %+v", msg.Type(), msg) + env := &wire.Envelope{ + Sender: c.sender(), + Recipient: peer, + Msg: msg, + } + eg.Go(func() error { return c.pub.Publish(ctx, env) }) + } + return errors.WithMessage(eg.Wait(), "publishing message") +} + +// Peers returns the ordered list of peer addresses. Note that the own peer is +// included in the list. +func (c *channelConn) Peers() []map[wallet.BackendID]wire.Address { + return c.peers +} + +// newUpdateResRecv creates a new update response receiver for the given version. +// The receiver should be closed after all expected responses are received. +// The receiver is also closed when the channel connection is closed. +func (c *channelConn) NewUpdateResRecv(version uint64) (*channelMsgRecv, error) { + recv := wire.NewReceiver() + if err := c.r.Subscribe(recv, func(e *wire.Envelope) bool { + resMsg, ok := e.Msg.(channelUpdateResMsg) + return ok && resMsg.Ver() == version + }); err != nil { + return nil, errors.WithMessagef(err, "subscribing update response receiver") + } + + return &channelMsgRecv{ + Receiver: recv, + peers: c.peers, + log: c.log.WithField("version", version), + }, nil +} + +// Close closes the broadcaster and update request receiver. +func (c *channelConn) Close() error { + return c.r.Close() +} + // newChannelConn creates a new channel connection for the given channel ID. It // subscribes on the subscriber to all messages regarding this channel. func newChannelConn(id channel.ID, peers []map[wallet.BackendID]wire.Address, idx channel.Index, sub wire.Subscriber, pub wire.Publisher) (_ *channelConn, err error) { @@ -85,62 +137,14 @@ func newChannelConn(id channel.ID, peers []map[wallet.BackendID]wire.Address, id }, nil } -func (c *channelConn) sender() map[wallet.BackendID]wire.Address { - return c.peers[c.idx] -} - // SetLog sets the logger of the channel connection. It is assumed to be // called once before usage of the connection, so it isn't thread-safe. func (c *channelConn) SetLog(l log.Logger) { c.log = l } -// Close closes the broadcaster and update request receiver. -func (c *channelConn) Close() error { - return c.r.Close() -} - -// Send broadcasts the message to all channel participants. -func (c *channelConn) Send(ctx context.Context, msg wire.Msg) error { - var eg errgroup.Group - for i, peer := range c.peers { - if channel.Index(i) == c.idx { - continue // skip own peer - } - c.log.WithField("peer", peer).Debugf("channelConn: publishing message: %v: %+v", msg.Type(), msg) - env := &wire.Envelope{ - Sender: c.sender(), - Recipient: peer, - Msg: msg, - } - eg.Go(func() error { return c.pub.Publish(ctx, env) }) - } - return errors.WithMessage(eg.Wait(), "publishing message") -} - -// Peers returns the ordered list of peer addresses. Note that the own peer is -// included in the list. -func (c *channelConn) Peers() []map[wallet.BackendID]wire.Address { - return c.peers -} - -// newUpdateResRecv creates a new update response receiver for the given version. -// The receiver should be closed after all expected responses are received. -// The receiver is also closed when the channel connection is closed. -func (c *channelConn) NewUpdateResRecv(version uint64) (*channelMsgRecv, error) { - recv := wire.NewReceiver() - if err := c.r.Subscribe(recv, func(e *wire.Envelope) bool { - resMsg, ok := e.Msg.(channelUpdateResMsg) - return ok && resMsg.Ver() == version - }); err != nil { - return nil, errors.WithMessagef(err, "subscribing update response receiver") - } - - return &channelMsgRecv{ - Receiver: recv, - peers: c.peers, - log: c.log.WithField("version", version), - }, nil +func (c *channelConn) sender() map[wallet.BackendID]wire.Address { + return c.peers[c.idx] } type ( @@ -168,5 +172,8 @@ func (r *channelMsgRecv) Next(ctx context.Context) (channel.Index, ChannelMsg, e if !ok { return 0, nil, errors.Errorf("unexpected message type: expected ChannelMsg, got %T", env.Msg) } + if idx < 0 || idx > math.MaxUint16 { + return 0, nil, errors.Errorf("channel connection received message from unexpected peer %v", env.Sender) + } return channel.Index(idx), msg, nil } diff --git a/client/client.go b/client/client.go index 2557d0ce9..efe54ce26 100644 --- a/client/client.go +++ b/client/client.go @@ -128,6 +128,27 @@ func (c *Client) Close() error { return err } +// Restore restores all channels from persistence. Channels are restored in +// parallel. Newly restored channels should be acquired through the +// OnNewChannel callback. +func (c *Client) Restore(ctx context.Context) error { + ps, err := c.pr.ActivePeers(ctx) + if err != nil { + return errors.WithMessage(err, "restoring active peers") + } + + var eg errgroup.Group + for _, p := range ps { + if channel.EqualWireMaps(p, c.address) { + continue // skip own peer + } + + eg.Go(func() error { return c.restorePeerChannels(ctx, p) }) + } + + return eg.Wait() +} + // OnNewChannel sets a callback to be called whenever a new channel is created // or restored. Only one such handler can be set at a time, and repeated calls // to this function will overwrite the currently existing handler. This function @@ -208,24 +229,3 @@ func (c *Client) logPeer(p map[wallet.BackendID]wire.Address) log.Logger { func (c *Client) logChan(id channel.ID) log.Logger { return c.log.WithField("channel", id) } - -// Restore restores all channels from persistence. Channels are restored in -// parallel. Newly restored channels should be acquired through the -// OnNewChannel callback. -func (c *Client) Restore(ctx context.Context) error { - ps, err := c.pr.ActivePeers(ctx) - if err != nil { - return errors.WithMessage(err, "restoring active peers") - } - - var eg errgroup.Group - for _, p := range ps { - if channel.EqualWireMaps(p, c.address) { - continue // skip own peer - } - p := p - eg.Go(func() error { return c.restorePeerChannels(ctx, p) }) - } - - return eg.Wait() -} diff --git a/client/client_internal_test.go b/client/client_internal_test.go index 7ef75c15a..673abcc30 100644 --- a/client/client_internal_test.go +++ b/client/client_internal_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" channeltest "perun.network/go-perun/channel/test" wiretest "perun.network/go-perun/wire/test" @@ -46,6 +47,6 @@ func TestClient_Channel(t *testing.T) { ch2, err := c.Channel(cID) assert.Same(t, ch2, ch1) - assert.NoError(t, err) + require.NoError(t, err) }) } diff --git a/client/client_role_test.go b/client/client_role_test.go index 09d0904d8..0de26193b 100644 --- a/client/client_role_test.go +++ b/client/client_role_test.go @@ -49,7 +49,7 @@ func NewSetups(rng *rand.Rand, names []string, bID wallet.BackendID) []ctest.Rol backend = ctest.NewMockBackend(rng, "1337") ) - for i := 0; i < n; i++ { + for i := range n { watcher, err := local.NewWatcher(backend) if err != nil { panic("Error initializing watcher: " + err.Error()) @@ -77,7 +77,7 @@ func NewSetups(rng *rand.Rand, names []string, bID wallet.BackendID) []ctest.Rol func runAliceBobTest(ctx context.Context, t *testing.T, setup func(*rand.Rand) ([]ctest.RoleSetup, [2]ctest.Executer)) { t.Helper() rng := test.Prng(t) - for i := 0; i < 2; i++ { + for i := range 2 { setups, roles := setup(rng) app := client.WithoutApp() if i == 1 { diff --git a/client/client_test.go b/client/client_test.go index 0963289e9..93bf7b18c 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -86,7 +86,7 @@ func TestClient_New(t *testing.T) { require.NoError(t, err, "initializing the watcher should not error") c, err := client.New(wiretest.NewRandomAddress(rng), &DummyBus{t}, &ctest.MockFunder{}, &ctest.MockAdjudicator{}, map[wallet.BackendID]wallet.Wallet{channel.TestBackendID: wtest.RandomWallet(channel.TestBackendID)}, watcher) - assert.NoError(t, err) + require.NoError(t, err) require.NotNil(t, c) } diff --git a/client/clientconn.go b/client/clientconn.go index 9ba36e369..02bd47880 100644 --- a/client/clientconn.go +++ b/client/clientconn.go @@ -34,6 +34,20 @@ type clientConn struct { log.Embedding } +// Publish publishes the message on the bus. Makes clientConn implement the +// wire.Publisher interface. +func (c *clientConn) Publish(ctx context.Context, env *wire.Envelope) error { + return c.bus.Publish(ctx, env) +} + +func (c *clientConn) Close() error { + err := c.Relay.Close() + if rerr := c.reqRecv.Close(); err == nil { + err = errors.WithMessage(rerr, "closing proposal receiver") + } + return err +} + func makeClientConn(address map[wallet.BackendID]wire.Address, bus wire.Bus) (c clientConn, err error) { c.Embedding = log.MakeEmbedding(log.WithField("id", address)) c.sender = address @@ -47,7 +61,7 @@ func makeClientConn(address map[wallet.BackendID]wire.Address, bus wire.Bus) (c } }() - c.Relay.SetDefaultMsgHandler(func(m *wire.Envelope) { + c.SetDefaultMsgHandler(func(m *wire.Envelope) { log.Debugf("Received %T message without subscription: %v", m.Msg, m) }) if err := bus.SubscribeClient(c, c.sender); err != nil { @@ -86,17 +100,3 @@ func (c *clientConn) pubMsg(ctx context.Context, msg wire.Msg, rec map[wallet.Ba Msg: msg, }) } - -// Publish publishes the message on the bus. Makes clientConn implement the -// wire.Publisher interface. -func (c *clientConn) Publish(ctx context.Context, env *wire.Envelope) error { - return c.bus.Publish(ctx, env) -} - -func (c *clientConn) Close() error { - err := c.Relay.Close() - if rerr := c.reqRecv.Close(); err == nil { - err = errors.WithMessage(rerr, "closing proposal receiver") - } - return err -} diff --git a/client/payment_test.go b/client/payment_test.go index b5e7923a4..5865eec4b 100644 --- a/client/payment_test.go +++ b/client/payment_test.go @@ -19,6 +19,7 @@ import ( "math/big" "math/rand" "testing" + "time" "perun.network/go-perun/channel" @@ -70,3 +71,45 @@ func TestPaymentDispute(t *testing.T) { } ctest.ExecuteTwoPartyTest(ctx, t, roles, cfg) } + +func TestPaymentChannelsOptimistic(t *testing.T) { + rng := pkgtest.Prng(t) + ctx, cancel := context.WithTimeout(context.Background(), testDuration) + defer cancel() + + setup := makePaymentChannelSetup(rng) + ctest.TestPaymentChannelOptimistic(ctx, t, setup) +} + +func TestPaymentChannelsDispute(t *testing.T) { + rng := pkgtest.Prng(t) + ctx, cancel := context.WithTimeout(context.Background(), testDuration) + defer cancel() + + setup := makePaymentChannelSetup(rng) + ctest.TestPaymentChannelDispute(ctx, t, setup) +} + +func makePaymentChannelSetup(rng *rand.Rand) ctest.PaymentChannelSetup { + return ctest.PaymentChannelSetup{ + Clients: createPaymentChannelClients(rng), + ChallengeDuration: challengeDuration, + Asset: chtest.NewRandomAsset(rng, channel.TestBackendID), + Balances: ctest.PaymentChannelBalances{ + InitBalsAliceBob: []*big.Int{big.NewInt(5), big.NewInt(5)}, + BalsUpdated: []*big.Int{big.NewInt(2), big.NewInt(8)}, + FinalBals: []*big.Int{big.NewInt(2), big.NewInt(8)}, + }, + BalanceDelta: big.NewInt(0), + Rng: rng, + WaitWatcherTimeout: 100 * time.Millisecond, + IsUTXO: true, + } +} + +func createPaymentChannelClients(rng *rand.Rand) [2]ctest.RoleSetup { + var setupsArray [2]ctest.RoleSetup + setups := NewSetups(rng, []string{"Alice", "Bob"}, channel.TestBackendID) + copy(setupsArray[:], setups) + return setupsArray +} diff --git a/client/proposal.go b/client/proposal.go index 9b7bb7b75..ed6ba1d92 100644 --- a/client/proposal.go +++ b/client/proposal.go @@ -190,7 +190,7 @@ func (c *Client) ProposeChannel(ctx context.Context, prop ChannelProposal) (*Cha // cache version 1 updates until channel is opened c.enableVer1Cache() // replay cached version 1 updates - defer c.releaseVer1Cache() + defer c.releaseVer1Cache() //nolint:contextcheck ch, err := c.proposeTwoPartyChannel(ctx, prop) if err != nil { return nil, errors.WithMessage(err, "channel proposal") @@ -267,7 +267,7 @@ func (c *Client) handleChannelProposalAcc( // cache version 1 updates c.enableVer1Cache() // replay cached version 1 updates - defer c.releaseVer1Cache() + defer c.releaseVer1Cache() //nolint:contextcheck if ch, err = c.acceptChannelProposal(ctx, prop, p, acc); err != nil { return ch, errors.WithMessage(err, "accept channel proposal") @@ -408,7 +408,7 @@ func (c *Client) validTwoPartyProposal( return errors.Errorf("expected 2 peers, got %d", len(peers)) } - if !(ourIdx == ProposerIdx || ourIdx == ProposeeIdx) { + if ourIdx != ProposerIdx && ourIdx != ProposeeIdx { return errors.Errorf("invalid index: %d", ourIdx) } @@ -454,7 +454,7 @@ func (c *Client) validSubChannelProposal(proposal *SubChannelProposalMsg) error return errors.New("parent channel and sub-channel backends do not match") } - if err := parentState.Balances.AssertGreaterOrEqual(base.InitBals.Balances); err != nil { + if err := parentState.AssertGreaterOrEqual(base.InitBals.Balances); err != nil { return errors.WithMessage(err, "insufficient funds") } @@ -501,7 +501,7 @@ func (c *Client) validVirtualChannelProposal(prop *VirtualChannelProposalMsg, ou } virtualBals := transformBalances(prop.InitBals.Balances, parentState.NumParts(), indexMap) - if err := parentState.Balances.AssertGreaterOrEqual(virtualBals); err != nil { + if err := parentState.AssertGreaterOrEqual(virtualBals); err != nil { return errors.WithMessage(err, "insufficient funds") } return nil @@ -574,6 +574,7 @@ func (c *Client) completeCPP( calcNonce(nonceShares(propBase.NonceShare, acc.Base().NonceShare)), prop.Type() == wire.LedgerChannelProposal, prop.Type() == wire.VirtualChannelProposal, + propBase.Aux, ) if c.channels.Has(params.ID()) { diff --git a/client/proposal_internal_test.go b/client/proposal_internal_test.go index ed45afaf0..498bc7b34 100644 --- a/client/proposal_internal_test.go +++ b/client/proposal_internal_test.go @@ -105,7 +105,7 @@ func TestChannelProposal_assertValidNumParts(t *testing.T) { func TestProposalResponder_Accept_Nil(t *testing.T) { p := new(ProposalResponder) - _, err := p.Accept(nil, new(LedgerChannelProposalAccMsg)) + _, err := p.Accept(nil, new(LedgerChannelProposalAccMsg)) //nolint:staticcheck assert.Error(t, err, "context") } diff --git a/client/proposalmsgs.go b/client/proposalmsgs.go index afa510529..8c7c07b1c 100644 --- a/client/proposalmsgs.go +++ b/client/proposalmsgs.go @@ -109,6 +109,7 @@ type ( InitData channel.Data // Initial App data. InitBals *channel.Allocation // Initial balances. FundingAgreement channel.Balances // Possibly different funding agreement from initial state's balances. + Aux channel.Aux // Auxiliary data. } // LedgerChannelProposalMsg is a channel proposal for ledger channels. @@ -125,59 +126,29 @@ type ( } ) -// proposalPeers returns the wire addresses of a proposed channel's -// participants. -func (c *Client) proposalPeers(p ChannelProposal) (peers []map[wallet.BackendID]wire.Address) { - switch prop := p.(type) { - case *LedgerChannelProposalMsg: - peers = prop.Peers - case *SubChannelProposalMsg: - ch, ok := c.channels.Channel(prop.Parent) - if !ok { - c.log.Panic("ProposalPeers: invalid parent channel") - } - peers = ch.Peers() - case *VirtualChannelProposalMsg: - peers = prop.Peers - default: - c.log.Panicf("ProposalPeers: unhandled proposal type %T") - } - return -} - -// makeBaseChannelProposal creates a BaseChannelProposal and applies the supplied -// options. For more information, see ProposalOpts. -func makeBaseChannelProposal( +// NewLedgerChannelProposal creates a ledger channel proposal and applies the +// supplied options. +// challengeDuration is the on-chain challenge duration in seconds. +// participant is our wallet address. +// initBals are the initial balances. +// peers are the wire addresses of the channel participants. +// For more information, see ProposalOpts. +func NewLedgerChannelProposal( challengeDuration uint64, + participant map[wallet.BackendID]wallet.Address, initBals *channel.Allocation, + peers []map[wallet.BackendID]wire.Address, opts ...ProposalOpts, -) (BaseChannelProposal, error) { - opt := union(opts...) - - fundingAgreement := initBals.Balances - if opt.isFundingAgreement() { - fundingAgreement = opt.fundingAgreement() - if equal, err := perunbig.EqualSum(initBals.Balances, fundingAgreement); err != nil { - return BaseChannelProposal{}, errors.WithMessage(err, "comparing FundingAgreement and initial balances sum") - } else if !equal { - return BaseChannelProposal{}, errors.New("FundingAgreement and initial balances differ") - } - } - - var proposalID ProposalID - if _, err := io.ReadFull(rand.Reader, proposalID[:]); err != nil { - return BaseChannelProposal{}, errors.Wrap(err, "generating proposal ID") +) (prop *LedgerChannelProposalMsg, err error) { + prop = &LedgerChannelProposalMsg{ + Participant: participant, + Peers: peers, } - - return BaseChannelProposal{ - ChallengeDuration: challengeDuration, - ProposalID: proposalID, - NonceShare: opt.nonce(), - App: opt.App(), - InitData: opt.AppData(), - InitBals: initBals, - FundingAgreement: fundingAgreement, - }, nil + prop.BaseChannelProposal, err = makeBaseChannelProposal( + challengeDuration, + initBals, + opts...) + return } // Base returns the channel proposal's common values. @@ -250,31 +221,6 @@ func (LedgerChannelProposalMsg) Matches(acc ChannelProposalAccept) bool { return ok } -// NewLedgerChannelProposal creates a ledger channel proposal and applies the -// supplied options. -// challengeDuration is the on-chain challenge duration in seconds. -// participant is our wallet address. -// initBals are the initial balances. -// peers are the wire addresses of the channel participants. -// For more information, see ProposalOpts. -func NewLedgerChannelProposal( - challengeDuration uint64, - participant map[wallet.BackendID]wallet.Address, - initBals *channel.Allocation, - peers []map[wallet.BackendID]wire.Address, - opts ...ProposalOpts, -) (prop *LedgerChannelProposalMsg, err error) { - prop = &LedgerChannelProposalMsg{ - Participant: participant, - Peers: peers, - } - prop.BaseChannelProposal, err = makeBaseChannelProposal( - challengeDuration, - initBals, - opts...) - return -} - // Type returns wire.LedgerChannelProposal. func (LedgerChannelProposalMsg) Type() wire.Type { return wire.LedgerChannelProposal @@ -304,14 +250,6 @@ func (p *LedgerChannelProposalMsg) Decode(r io.Reader) error { return p.assertValidNumParts() } -func (p LedgerChannelProposalMsg) assertValidNumParts() error { - if len(p.Peers) < 2 || len(p.Peers) > channel.MaxNumParts { - return errors.Errorf("expected 2-%d participants, got %d", - channel.MaxNumParts, len(p.Peers)) - } - return nil -} - // Valid checks whether the participant address is nil. func (p LedgerChannelProposalMsg) Valid() error { if err := p.BaseChannelProposal.Valid(); err != nil { @@ -379,6 +317,70 @@ func (SubChannelProposalMsg) Matches(acc ChannelProposalAccept) bool { return ok } +// proposalPeers returns the wire addresses of a proposed channel's +// participants. +func (c *Client) proposalPeers(p ChannelProposal) (peers []map[wallet.BackendID]wire.Address) { + switch prop := p.(type) { + case *LedgerChannelProposalMsg: + peers = prop.Peers + case *SubChannelProposalMsg: + ch, ok := c.channels.Channel(prop.Parent) + if !ok { + c.log.Panic("ProposalPeers: invalid parent channel") + } + peers = ch.Peers() + case *VirtualChannelProposalMsg: + peers = prop.Peers + default: + c.log.Panicf("ProposalPeers: unhandled proposal type %T") + } + return +} + +// makeBaseChannelProposal creates a BaseChannelProposal and applies the supplied +// options. For more information, see ProposalOpts. +func makeBaseChannelProposal( + challengeDuration uint64, + initBals *channel.Allocation, + opts ...ProposalOpts, +) (BaseChannelProposal, error) { + opt := union(opts...) + + fundingAgreement := initBals.Balances + if opt.isFundingAgreement() { + fundingAgreement = opt.fundingAgreement() + if equal, err := perunbig.EqualSum(initBals.Balances, fundingAgreement); err != nil { + return BaseChannelProposal{}, errors.WithMessage(err, "comparing FundingAgreement and initial balances sum") + } else if !equal { + return BaseChannelProposal{}, errors.New("FundingAgreement and initial balances differ") + } + } + + var proposalID ProposalID + if _, err := io.ReadFull(rand.Reader, proposalID[:]); err != nil { + return BaseChannelProposal{}, errors.Wrap(err, "generating proposal ID") + } + + return BaseChannelProposal{ + ChallengeDuration: challengeDuration, + ProposalID: proposalID, + NonceShare: opt.nonce(), + App: opt.App(), + InitData: opt.AppData(), + InitBals: initBals, + FundingAgreement: fundingAgreement, + Aux: opt.aux(), + }, nil +} + +func (p LedgerChannelProposalMsg) assertValidNumParts() error { + if len(p.Peers) < 2 || len(p.Peers) > channel.MaxNumParts { + return errors.Errorf("expected 2-%d participants, got %d", + channel.MaxNumParts, len(p.Peers)) + } + return nil +} + type ( // ChannelProposalAccept is the generic interface for channel proposal // accept messages. diff --git a/client/proposalopts.go b/client/proposalopts.go index ab1fbd48e..fa080534e 100644 --- a/client/proposalopts.go +++ b/client/proposalopts.go @@ -27,7 +27,7 @@ import ( // NoData is set, and a random nonce share is generated. type ProposalOpts map[string]interface{} -var optNames = struct{ nonce, app, appData, fundingAgreement string }{nonce: "nonce", app: "app", appData: "appData", fundingAgreement: "fundingAgreement"} +var optNames = struct{ nonce, app, appData, fundingAgreement, aux string }{nonce: "nonce", app: "app", appData: "appData", fundingAgreement: "fundingAgreement", aux: "aux"} // App returns the option's configured app. func (o ProposalOpts) App() channel.App { @@ -92,6 +92,19 @@ func (o ProposalOpts) nonce() NonceShare { return share } +// aux returns the option's configured auxiliary data. +func (o ProposalOpts) aux() channel.Aux { + a, ok := o[optNames.aux] + if !ok { + return channel.ZeroAux + } + aux, ok := a.(channel.Aux) + if !ok { + log.Panicf("wrong type: expected []byte, got %T", a) + } + return aux +} + // isNonce returns whether a ProposalOpts contains a manually set nonce. func (o ProposalOpts) isNonce() bool { _, ok := o[optNames.nonce] @@ -122,6 +135,11 @@ func WithNonce(share NonceShare) ProposalOpts { return ProposalOpts{optNames.nonce: share} } +// WithAux configures an auxiliary data field. +func WithAux(aux channel.Aux) ProposalOpts { + return ProposalOpts{optNames.aux: aux} +} + // WithNonceFrom reads a nonce share from a reader (should be random stream). func WithNonceFrom(r io.Reader) ProposalOpts { var share NonceShare diff --git a/client/restore_internal_test.go b/client/restore_internal_test.go index 902e1a986..c31917804 100644 --- a/client/restore_internal_test.go +++ b/client/restore_internal_test.go @@ -87,7 +87,7 @@ func TestRestoreChannelCollection(t *testing.T) { // Generate multiple trees of channels into one collection. db := make(map[channel.ID]*persistence.Channel) - for i := 0; i < 3; i++ { + for range 3 { mkRndChanTree(rng, 3, 1, 3, db, channel.TestBackendID) } @@ -104,7 +104,7 @@ func TestRestoreChannelCollection(t *testing.T) { // Restore all channels into the client and check the published channels. c.restoreChannelCollection(db, patchChFromSource) - require.Equal(t, len(witnessedChans), len(db), "channel count mismatch") + require.Len(t, witnessedChans, len(db), "channel count mismatch") // Duplicates should be ignored and there should be no missing channels. c.OnNewChannel(func(*Channel) { @@ -120,7 +120,7 @@ func mkRndChan(rng *rand.Rand, bID wallet.BackendID) *persistence.Channel { parts[i] = map[wallet.BackendID]wallet.Address{bID: wallettest.NewRandomAccount(rng, bID).Address()} } ch := persistence.NewChannel() - ch.IdxV = channel.Index(rng.Intn(channel.MaxNumParts)) + ch.IdxV = channel.Index(rng.Intn(channel.MaxNumParts)) //nolint:gosec ch.ParamsV = test.NewRandomParams(rng, test.WithParts(parts)) sigs := make([]bool, channel.MaxNumParts) opts := test.WithParams(ch.ParamsV) @@ -147,7 +147,7 @@ func mkRndChanTree( if minChildren > 0 { minChildren-- } - for i := 0; i < children; i++ { + for range children { t := mkRndChanTree(rng, depth-1, minChildren, maxChildren-1, db, bID) t.Parent = new(channel.ID) *t.Parent = root.ID() diff --git a/client/serialize.go b/client/serialize.go index 365fc133a..e4c752228 100644 --- a/client/serialize.go +++ b/client/serialize.go @@ -16,6 +16,7 @@ package client import ( "io" + "math" "github.com/pkg/errors" "perun.network/go-perun/channel" @@ -31,7 +32,11 @@ type ( // Encode encodes the object to the writer. func (a channelIDsWithLen) Encode(w io.Writer) (err error) { - err = perunio.Encode(w, sliceLen(len(a))) + l := len(a) + if l > math.MaxUint16 { + return errors.New("slice length too long") + } + err = perunio.Encode(w, sliceLen(l)) if err != nil { return } @@ -66,7 +71,11 @@ func (a *channelIDsWithLen) Decode(r io.Reader) (err error) { // Encode encodes the object to the writer. func (a indexMapsWithLen) Encode(w io.Writer) (err error) { - err = perunio.Encode(w, sliceLen(len(a))) + l := len(a) + if l > math.MaxUint16 { + return errors.New("slice length too long") + } + err = perunio.Encode(w, sliceLen(l)) if err != nil { return } @@ -98,7 +107,11 @@ func (a *indexMapsWithLen) Decode(r io.Reader) (err error) { // Encode encodes the object to the writer. func (a indexMapWithLen) Encode(w io.Writer) (err error) { - err = perunio.Encode(w, sliceLen(len(a))) + l := len(a) + if l > math.MaxUint16 { + return errors.New("slice length too long") + } + err = perunio.Encode(w, sliceLen(l)) if err != nil { return } diff --git a/client/subchannel.go b/client/subchannel.go index 117428202..73ad92b39 100644 --- a/client/subchannel.go +++ b/client/subchannel.go @@ -53,7 +53,7 @@ func (c *Channel) fundSubChannel(ctx context.Context, id channel.ID, alloc *chan // equal assets and sufficient balances are already checked when validating the sub-channel proposal // withdraw initial balances into sub-allocation - state.Allocation.Balances = state.Allocation.Balances.Sub(alloc.Balances) + state.Balances = state.Sub(alloc.Balances) state.AddSubAlloc(*channel.NewSubAlloc(id, alloc.Balances.Sum(), nil)) return nil @@ -97,19 +97,19 @@ func (c *Channel) withdrawSubChannel(ctx context.Context, sub *Channel) error { c.Log().Panicf("sub-allocation %x not found", subAlloc.ID) } - if !subAlloc.BalancesEqual(sub.machine.State().Allocation.Sum()) { + if !subAlloc.BalancesEqual(sub.machine.State().Sum()) { c.Log().Panic("sub-allocation does not equal accumulated sub-channel outcome") } // asset types of this channel and parent channel are assumed to be the same for a, assetBalances := range sub.machine.State().Balances { for u, userBalance := range assetBalances { - parentBalance := parentState.Allocation.Balances[a][u] + parentBalance := parentState.Balances[a][u] parentBalance.Add(parentBalance, userBalance) } } - if err := parentState.Allocation.RemoveSubAlloc(subAlloc); err != nil { + if err := parentState.RemoveSubAlloc(subAlloc); err != nil { c.Log().WithError(err).Panicf("removing sub-allocation with id %x", subAlloc.ID) } diff --git a/client/sync.go b/client/sync.go index ab852e416..7ec29e784 100644 --- a/client/sync.go +++ b/client/sync.go @@ -67,8 +67,10 @@ func (c *Client) handleSyncMsg(peer map[wallet.BackendID]wire.Address, msg *Chan } } -// syncChannel synchronizes the channel state with the given peer and modifies +// SyncChannel synchronizes the channel state with the given peer and modifies // the current state if required. +// +//nolint:unused func (c *Client) syncChannel(ctx context.Context, ch *persistence.Channel, p map[wallet.BackendID]wire.Address) (err error) { recv := wire.NewReceiver() defer recv.Close() // ignore error @@ -119,7 +121,7 @@ func (c *Client) syncChannel(ctx context.Context, ch *persistence.Channel, p map // validateMessage validates the remote channel sync message. // -//nolint:nestif +//nolint:nestif, unused func validateMessage(ch *persistence.Channel, msg *ChannelSyncMsg) error { v := ch.CurrentTX().Version mv := msg.CurrentTX.Version @@ -128,7 +130,7 @@ func validateMessage(ch *persistence.Channel, msg *ChannelSyncMsg) error { return errors.New("channel ID mismatch") } if mv == v { - if err := msg.CurrentTX.State.Equal(ch.CurrentTX().State); err != nil { + if err := msg.CurrentTX.Equal(ch.CurrentTX().State); err != nil { return errors.WithMessage(err, "different states for same version") } } else if mv > v { @@ -151,6 +153,7 @@ func validateMessage(ch *persistence.Channel, msg *ChannelSyncMsg) error { return nil } +//nolint:unused func revisePhase(ch *persistence.Channel) error { //nolint:gocritic if ch.PhaseV <= channel.Funding && ch.CurrentTXV.Version == 0 { diff --git a/client/test/alice.go b/client/test/alice.go index 2c633e3a3..69e41271a 100644 --- a/client/test/alice.go +++ b/client/test/alice.go @@ -50,14 +50,14 @@ func (r *Alice) exec(_cfg ExecConfig, ch *paymentChannel) { we, them := r.Idxs(cfg.Peers()) // 1st Alice receives some updates from Bob - for i := 0; i < cfg.NumPayments[them]; i++ { + for i := range cfg.NumPayments[them] { ch.recvTransfer(cfg.TxAmounts[them], fmt.Sprintf("Bob#%d", i)) } // 2nd stage r.waitStage() // 2nd Alice sends some updates to Bob - for i := 0; i < cfg.NumPayments[we]; i++ { + for i := range cfg.NumPayments[we] { ch.sendTransfer(cfg.TxAmounts[we], fmt.Sprintf("Alice#%d", i)) } // 3rd stage diff --git a/client/test/backend.go b/client/test/backend.go index 29af86113..1825c3d49 100644 --- a/client/test/backend.go +++ b/client/test/backend.go @@ -18,6 +18,7 @@ import ( "context" "encoding" "fmt" + "math" "math/big" "math/rand" "time" @@ -191,7 +192,11 @@ func (b *MockBackend) Register(_ context.Context, req channel.AdjudicatorReq, su }, }, subChannels...) - timeout := time.Now().Add(time.Duration(req.Params.ChallengeDuration) * time.Millisecond) + duration := req.Params.ChallengeDuration + if duration > math.MaxInt64 { + return fmt.Errorf("challenge duration %d is too large", duration) + } + timeout := time.Now().Add(time.Duration(duration) * time.Millisecond) for _, ch := range channels { b.setLatestEvent( ch.Params.ID(), @@ -207,20 +212,23 @@ func (b *MockBackend) Register(_ context.Context, req channel.AdjudicatorReq, su return nil } -func (b *MockBackend) setLatestEvent(ch channel.ID, e channel.AdjudicatorEvent) { - b.latestEvents[ch] = e - // Update subscriptions. - if channelSubs, ok := b.eventSubs[ch]; ok { - for _, sub := range channelSubs { - // Remove previous latest event. - select { - case <-sub.events: - default: - } - // Add latest event. - sub.events <- e - } +// Subscribe creates an event subscription. +func (b *MockBackend) Subscribe(ctx context.Context, chID channel.ID) (channel.AdjudicatorSubscription, error) { + b.log.Infof("SubscribeRegistered: %+v", chID) + + b.mu.Lock() + defer b.mu.Unlock() + + sub := NewMockSubscription(ctx) + sub.onClose = func() { b.removeSubscription(chID, sub) } + b.eventSubs[chID] = append(b.eventSubs[chID], sub) + + // Feed latest event if any. + if e, ok := b.latestEvents[chID]; ok { + sub.events <- e } + + return sub, nil } // Progress progresses the channel state. @@ -229,8 +237,11 @@ func (b *MockBackend) Progress(_ context.Context, req channel.ProgressReq) error b.mu.Lock() defer b.mu.Unlock() - - timeout := time.Now().Add(time.Duration(req.Params.ChallengeDuration) * time.Millisecond) + duration := req.Params.ChallengeDuration + if duration > math.MaxInt64 { + return fmt.Errorf("challenge duration %d is too large", duration) + } + timeout := time.Now().Add(time.Duration(duration) * time.Millisecond) b.setLatestEvent( req.Params.ID(), channel.NewProgressedEvent( @@ -243,11 +254,113 @@ func (b *MockBackend) Progress(_ context.Context, req channel.ProgressReq) error return nil } +// Withdraw withdraws the channel funds. +func (b *MockBackend) Withdraw(_ context.Context, req channel.AdjudicatorReq, subStates channel.StateMap, acc wallet.Address) error { + b.mu.Lock() + defer b.mu.Unlock() + + // Check withdraw requirements. + states := make([]*channel.State, 1+len(subStates)) + states[0] = req.Tx.State + i := 1 + for _, s := range subStates { + states[i] = s.State + i++ + } + if err := b.checkStates(states, checkWithdraw); err != nil { + return err + } + + // Redistribute balances if not done already. + b.assetHolder.mtx.Lock() + defer b.assetHolder.mtx.Unlock() + ch := req.Params.ID() + if !b.isConcluded(ch) { + outcome := outcomeRecursive(req.Tx.State, subStates) + b.log.Infof("Withdraw: %+v, %+v, %+v", req, subStates, outcome) + outcomeSum := outcome.Sum() + + funding := b.assetHolder.balances[ch] + if funding == nil { + funding = channel.MakeBalances(len(req.Tx.Assets), req.Tx.NumParts()) + } + fundingSum := funding.Sum() + + for a, assetOutcome := range outcome { + // If underfunded, don't redistribute balances. + if fundingSum[a].Cmp(outcomeSum[a]) < 0 { + continue + } + for p, amount := range assetOutcome { + funding[a][p].Set(amount) + } + } + } + + // Payout balances. + balances := b.assetHolder.balances[ch] + for a, assetBalances := range balances { + asset := req.Tx.Assets[a] + p := req.Idx + amount := assetBalances[p] + b.addBalance(acc, asset, amount) + amount.Set(big.NewInt(0)) + } + + if !b.isConcluded(ch) { + b.setLatestEvent(ch, channel.NewConcludedEvent(ch, &channel.ElapsedTimeout{}, req.Tx.Version)) + } + return nil +} + +// MockBalanceReader is a balance reader used for testing. At initialization, it +// is associated with a given account. +type MockBalanceReader struct { + b *MockBackend + acc wallet.Address +} + +// Balance returns the balance of the associated account for the given asset. +func (br *MockBalanceReader) Balance(asset channel.Asset) channel.Bal { + return br.b.Balance(br.acc, asset) +} + +// NewBalanceReader creates balance for the given account. +func (b *MockBackend) NewBalanceReader(acc wallet.Address) *MockBalanceReader { + return &MockBalanceReader{ + b: b, + acc: acc, + } +} + +// Balance returns the balance for the participant and asset. +func (b *MockBackend) Balance(p wallet.Address, a channel.Asset) *big.Int { + b.mu.Lock() + defer b.mu.Unlock() + return b.balance(p, a) +} + +func (b *MockBackend) setLatestEvent(ch channel.ID, e channel.AdjudicatorEvent) { + b.latestEvents[ch] = e + // Update subscriptions. + if channelSubs, ok := b.eventSubs[ch]; ok { + for _, sub := range channelSubs { + // Remove previous latest event. + select { + case <-sub.events: + default: + } + // Add latest event. + sub.events <- e + } + } +} + // outcomeRecursive returns the accumulated outcome of the channel and its sub-channels. func outcomeRecursive(state *channel.State, subStates channel.StateMap) (outcome channel.Balances) { outcome = state.Balances.Clone() for _, subAlloc := range state.Locked { - subOutcome := outcomeRecursive(subStates[subAlloc.ID], subStates) + subOutcome := outcomeRecursive(subStates[subAlloc.ID].State, subStates) for a, bals := range subOutcome { for p, bal := range bals { _p := p @@ -303,63 +416,16 @@ func (b *MockBackend) checkState(s *channel.State, op checkStateFunc) error { return nil } -// Withdraw withdraws the channel funds. -func (b *MockBackend) Withdraw(_ context.Context, req channel.AdjudicatorReq, subStates channel.StateMap, acc wallet.Address) error { - b.mu.Lock() - defer b.mu.Unlock() - - // Check withdraw requirements. - states := make([]*channel.State, 1+len(subStates)) - states[0] = req.Tx.State - i := 1 - for _, s := range subStates { - states[i] = s - i++ - } - if err := b.checkStates(states, checkWithdraw); err != nil { - return err - } - - // Redistribute balances if not done already. - b.assetHolder.mtx.Lock() - defer b.assetHolder.mtx.Unlock() - ch := req.Params.ID() - if !b.isConcluded(ch) { - outcome := outcomeRecursive(req.Tx.State, subStates) - b.log.Infof("Withdraw: %+v, %+v, %+v", req, subStates, outcome) - outcomeSum := outcome.Sum() - - funding := b.assetHolder.balances[ch] - if funding == nil { - funding = channel.MakeBalances(len(req.Tx.Assets), req.Tx.NumParts()) - } - fundingSum := funding.Sum() - - for a, assetOutcome := range outcome { - // If underfunded, don't redistribute balances. - if fundingSum[a].Cmp(outcomeSum[a]) < 0 { - continue - } - for p, amount := range assetOutcome { - funding[a][p].Set(amount) - } - } - } - - // Payout balances. - balances := b.assetHolder.balances[ch] - for a, assetBalances := range balances { - asset := req.Tx.Allocation.Assets[a] - p := req.Idx - amount := assetBalances[p] - b.addBalance(acc, asset, amount) - amount.Set(big.NewInt(0)) - } - - if !b.isConcluded(ch) { - b.setLatestEvent(ch, channel.NewConcludedEvent(ch, &channel.ElapsedTimeout{}, req.Tx.Version)) +func (b *MockBackend) setBalance(p wallet.Address, a channel.Asset, v *big.Int) { + partKey := newAddressMapKey(p) + partBals, ok := b.balances[partKey] + if !ok { + log.Debug("part not found", p) + partBals = make(map[string]*big.Int) + b.balances[partKey] = partBals } - return nil + log.Debug("set balance:", p, v) + partBals[newAssetMapKey(a)] = new(big.Int).Set(v) } func (b *MockBackend) isConcluded(ch channel.ID) bool { @@ -418,64 +484,6 @@ func encodableAsString(e encoding.BinaryMarshaler) string { return string(buff) } -// MockBalanceReader is a balance reader used for testing. At initialization, it -// is associated with a given account. -type MockBalanceReader struct { - b *MockBackend - acc wallet.Address -} - -// Balance returns the balance of the associated account for the given asset. -func (br *MockBalanceReader) Balance(asset channel.Asset) channel.Bal { - return br.b.Balance(br.acc, asset) -} - -// NewBalanceReader creates balance for the given account. -func (b *MockBackend) NewBalanceReader(acc wallet.Address) *MockBalanceReader { - return &MockBalanceReader{ - b: b, - acc: acc, - } -} - -// Balance returns the balance for the participant and asset. -func (b *MockBackend) Balance(p wallet.Address, a channel.Asset) *big.Int { - b.mu.Lock() - defer b.mu.Unlock() - return b.balance(p, a) -} - -func (b *MockBackend) setBalance(p wallet.Address, a channel.Asset, v *big.Int) { - partKey := newAddressMapKey(p) - partBals, ok := b.balances[partKey] - if !ok { - log.Debug("part not found", p) - partBals = make(map[string]*big.Int) - b.balances[partKey] = partBals - } - log.Debug("set balance:", p, v) - partBals[newAssetMapKey(a)] = new(big.Int).Set(v) -} - -// Subscribe creates an event subscription. -func (b *MockBackend) Subscribe(ctx context.Context, chID channel.ID) (channel.AdjudicatorSubscription, error) { - b.log.Infof("SubscribeRegistered: %+v", chID) - - b.mu.Lock() - defer b.mu.Unlock() - - sub := NewMockSubscription(ctx) - sub.onClose = func() { b.removeSubscription(chID, sub) } - b.eventSubs[chID] = append(b.eventSubs[chID], sub) - - // Feed latest event if any. - if e, ok := b.latestEvents[chID]; ok { - sub.events <- e - } - - return sub, nil -} - func (b *MockBackend) removeSubscription(ch channel.ID, sub *MockSubscription) { b.mu.Lock() defer b.mu.Unlock() @@ -516,23 +524,6 @@ func newAssetHolder(rng rng) *assetHolder { } } -// initFund initializes the funded WaitGroups for a channel if not already -// initialized. -// -// Must be called before using the Funder for a funding request. -func (f *assetHolder) initFund(req channel.FundingReq) { - f.mtx.Lock() - defer f.mtx.Unlock() - - if f.fundedWgs[req.Params.ID()] == nil { - f.fundedWgs[req.Params.ID()] = &sync.WaitGroup{} - f.fundedWgs[req.Params.ID()].Add(len(req.Params.Parts)) - } - if f.balances[req.Params.ID()] == nil { - f.balances[req.Params.ID()] = channel.MakeBalances(len(req.State.Assets), req.State.NumParts()) - } -} - // Fund simulates funding the channel. func (f *assetHolder) Fund(req channel.FundingReq, b *MockBackend, acc wallet.Address) { f.initFund(req) @@ -561,7 +552,11 @@ func (f *assetHolder) Fund(req channel.FundingReq, b *MockBackend, acc wallet.Ad // WaitForFunding waits until all participants have funded the channel. func (f *assetHolder) WaitForFunding(ctx context.Context, req channel.FundingReq) error { - challengeDuration := time.Duration(req.Params.ChallengeDuration) * time.Second + duration := req.Params.ChallengeDuration + if duration > math.MaxInt64 { + return fmt.Errorf("challenge duration %d is too large", duration) + } + challengeDuration := time.Duration(duration) * time.Second fundCtx, cancel := context.WithTimeout(ctx, challengeDuration) defer cancel() @@ -574,6 +569,23 @@ func (f *assetHolder) WaitForFunding(ctx context.Context, req channel.FundingReq } } +// initFund initializes the funded WaitGroups for a channel if not already +// initialized. +// +// Must be called before using the Funder for a funding request. +func (f *assetHolder) initFund(req channel.FundingReq) { + f.mtx.Lock() + defer f.mtx.Unlock() + + if f.fundedWgs[req.Params.ID()] == nil { + f.fundedWgs[req.Params.ID()] = &sync.WaitGroup{} + f.fundedWgs[req.Params.ID()].Add(len(req.Params.Parts)) + } + if f.balances[req.Params.ID()] == nil { + f.balances[req.Params.ID()] = channel.MakeBalances(len(req.State.Assets), req.State.NumParts()) + } +} + // MockSubscription is a subscription for MockBackend. type MockSubscription struct { events chan channel.AdjudicatorEvent diff --git a/client/test/bob.go b/client/test/bob.go index de215f6bf..89dcbda86 100644 --- a/client/test/bob.go +++ b/client/test/bob.go @@ -40,14 +40,14 @@ func (r *Bob) exec(_cfg ExecConfig, ch *paymentChannel, propHandler *acceptNextP we, them := r.Idxs(cfg.Peers()) // 1st Bob sends some updates to Alice - for i := 0; i < cfg.NumPayments[we]; i++ { + for i := range cfg.NumPayments[we] { ch.sendTransfer(cfg.TxAmounts[we], fmt.Sprintf("Bob#%d", i)) } // 2nd stage r.waitStage() // 2nd Bob receives some updates from Alice - for i := 0; i < cfg.NumPayments[them]; i++ { + for i := range cfg.NumPayments[them] { ch.recvTransfer(cfg.TxAmounts[them], fmt.Sprintf("Alice#%d", i)) } // 3rd stage diff --git a/client/test/carol.go b/client/test/carol.go index 518de1f5c..2fef85195 100644 --- a/client/test/carol.go +++ b/client/test/carol.go @@ -27,14 +27,6 @@ type Carol struct { registered chan *channel.RegisteredEvent } -// HandleAdjudicatorEvent is the callback for adjudicator event handling. -func (r *Carol) HandleAdjudicatorEvent(e channel.AdjudicatorEvent) { - r.log.Infof("HandleAdjudicatorEvent: %v", e) - if e, ok := e.(*channel.RegisteredEvent); ok { - r.registered <- e - } -} - // NewCarol creates a new Responder that executes the Carol protocol. func NewCarol(t *testing.T, setup RoleSetup) *Carol { t.Helper() @@ -44,6 +36,14 @@ func NewCarol(t *testing.T, setup RoleSetup) *Carol { } } +// HandleAdjudicatorEvent is the callback for adjudicator event handling. +func (r *Carol) HandleAdjudicatorEvent(e channel.AdjudicatorEvent) { + r.log.Infof("HandleAdjudicatorEvent: %v", e) + if e, ok := e.(*channel.RegisteredEvent); ok { + r.registered <- e + } +} + // Execute executes the Carol protocol. func (r *Carol) Execute(cfg ExecConfig) { r.Responder.Execute(cfg, r.exec) @@ -64,7 +64,7 @@ func (r *Carol) exec(_cfg ExecConfig, ch *paymentChannel, propHandler *acceptNex r.waitStage() // Carol receives some updates from Mallory - for i := 0; i < cfg.NumPayments[them]; i++ { + for i := range cfg.NumPayments[them] { ch.recvTransfer(cfg.TxAmounts[them], fmt.Sprintf("Mallory#%d", i)) } // 2nd stage - txs received diff --git a/client/test/channel.go b/client/test/channel.go index 2162d851d..28b7c6c9e 100644 --- a/client/test/channel.go +++ b/client/test/channel.go @@ -61,6 +61,22 @@ func newPaymentChannel(ch *client.Channel, r *role) *paymentChannel { } } +// The payment channel is its own update handler. +func (ch *paymentChannel) Handle(up client.ChannelUpdate, res *client.UpdateResponder) { + ch.log.Infof("Incoming channel update: %v", up) + ctx, cancel := context.WithTimeout(context.Background(), ch.r.timeout) + defer cancel() + + accept := <-ch.handler + if accept { + ch.log.Debug("Accepting...") + ch.res <- handlerRes{up, res.Accept(ctx)} + } else { + ch.log.Debug("Rejecting...") + ch.res <- handlerRes{up, res.Reject(ctx, "Rejection")} + } +} + func (ch *paymentChannel) openSubChannel( rng io.Reader, cfg ExecConfig, @@ -198,22 +214,6 @@ func (ch *paymentChannel) settleImpl(secondary bool) { } } -// The payment channel is its own update handler. -func (ch *paymentChannel) Handle(up client.ChannelUpdate, res *client.UpdateResponder) { - ch.log.Infof("Incoming channel update: %v", up) - ctx, cancel := context.WithTimeout(context.Background(), ch.r.timeout) - defer cancel() - - accept := <-ch.handler - if accept { - ch.log.Debug("Accepting...") - ch.res <- handlerRes{up, res.Accept(ctx)} - } else { - ch.log.Debug("Rejecting...") - ch.res <- handlerRes{up, res.Reject(ctx, "Rejection")} - } -} - func transferBal(bals []channel.Bal, ourIdx channel.Index, amount *big.Int) { a := new(big.Int).Set(amount) // local copy because we mutate it otherIdx := ourIdx ^ 1 diff --git a/client/test/fund.go b/client/test/fund.go index 448e047a9..4f61669a8 100644 --- a/client/test/fund.go +++ b/client/test/fund.go @@ -109,6 +109,7 @@ func runFredFridaTest( // New channels and errors are passed via the corresponding Go channels. chsFred := make(chan *client.Channel, 1) errsFred := make(chan error, 1) + //nolint:contextcheck go fred.Handle( AlwaysAcceptChannelHandler(ctx, fredWalletAddr, chsFred, errsFred), AlwaysRejectUpdateHandler(ctx, errsFred), diff --git a/client/test/handler.go b/client/test/handler.go index 72c815f6c..aadfd2196 100644 --- a/client/test/handler.go +++ b/client/test/handler.go @@ -70,7 +70,7 @@ func AlwaysAcceptUpdateHandler(ctx context.Context, errs chan error) client.Upda // AlwaysRejectUpdateHandler returns a channel update handler that rejects all // channel updates. func AlwaysRejectUpdateHandler(ctx context.Context, errs chan error) client.UpdateHandlerFunc { - return func(state *channel.State, update client.ChannelUpdate, responder *client.UpdateResponder) { + return func(_ *channel.State, update client.ChannelUpdate, responder *client.UpdateResponder) { err := responder.Reject(ctx, "") if err != nil { errs <- errors.WithMessage(err, "rejecting channel update") diff --git a/client/test/mallory.go b/client/test/mallory.go index ef30ec27d..0075ebac8 100644 --- a/client/test/mallory.go +++ b/client/test/mallory.go @@ -59,14 +59,15 @@ func (r *Mallory) exec(_cfg ExecConfig, ch *paymentChannel) { r.waitStage() // Mallory sends some updates to Carol - for i := 0; i < cfg.NumPayments[we]; i++ { + for i := range cfg.NumPayments[we] { ch.sendTransfer(cfg.TxAmounts[we], fmt.Sprintf("Mallory#%d", i)) } // 2nd stage - txs sent r.waitStage() // Register version 0 AdjudicatorReq - challengeDuration := time.Duration(ch.Channel.Params().ChallengeDuration) * time.Second + duration := ch.Channel.Params().ChallengeDuration + challengeDuration := time.Duration(duration) * time.Second //nolint:gosec regCtx, regCancel := context.WithTimeout(context.Background(), r.timeout) defer regCancel() r.log.Debug("Registering version 0 state.") diff --git a/client/test/multiledger.go b/client/test/multiledger.go index 7aa275136..f991ea894 100644 --- a/client/test/multiledger.go +++ b/client/test/multiledger.go @@ -71,17 +71,17 @@ func SetupMultiLedgerTest(t *testing.T) MultiLedgerSetup { Client2: c2, Asset1: a1, Asset2: a2, - //nolint:gomnd // We allow the balances to be magic numbers. + //nolint:mnd // We allow the balances to be magic numbers. InitBalances: channel.Balances{ {big.NewInt(10), big.NewInt(0)}, // Asset 1. {big.NewInt(0), big.NewInt(10)}, // Asset 2. }, - //nolint:gomnd + //nolint:mnd UpdateBalances1: channel.Balances{ {big.NewInt(5), big.NewInt(5)}, // Asset 1. {big.NewInt(3), big.NewInt(7)}, // Asset 2. }, - //nolint:gomnd + //nolint:mnd UpdateBalances2: channel.Balances{ {big.NewInt(1), big.NewInt(9)}, // Asset 1. {big.NewInt(5), big.NewInt(5)}, // Asset 2. @@ -96,11 +96,6 @@ type MultiLedgerAsset struct { asset channel.Asset } -// LedgerBackendID returns the asset's ID. -func (a *MultiLedgerAsset) LedgerBackendID() multi.LedgerBackendID { - return a.id -} - // NewMultiLedgerAsset returns a new multi-ledger asset. func NewMultiLedgerAsset(id multi.LedgerBackendID, asset channel.Asset) *MultiLedgerAsset { return &MultiLedgerAsset{ @@ -109,6 +104,11 @@ func NewMultiLedgerAsset(id multi.LedgerBackendID, asset channel.Asset) *MultiLe } } +// LedgerBackendID returns the asset's ID. +func (a *MultiLedgerAsset) LedgerBackendID() multi.LedgerBackendID { + return a.id +} + // Equal returns whether the two assets are equal. func (a *MultiLedgerAsset) Equal(b channel.Asset) bool { bm, ok := b.(*MultiLedgerAsset) diff --git a/client/test/multiledger_dispute.go b/client/test/multiledger_dispute.go index cabf66c90..129dd8c2c 100644 --- a/client/test/multiledger_dispute.go +++ b/client/test/multiledger_dispute.go @@ -79,10 +79,12 @@ func TestMultiLedgerDispute( // Setup proposal handler. channels := make(chan *client.Channel, 1) errs := make(chan error) + //nolint:contextcheck go alice.Handle( AlwaysRejectChannelHandler(ctx, errs), AlwaysAcceptUpdateHandler(ctx, errs), ) + //nolint:contextcheck go bob.Handle( AlwaysAcceptChannelHandler(ctx, bob.WalletAddress, channels, errs), AlwaysAcceptUpdateHandler(ctx, errs), @@ -99,11 +101,12 @@ func TestMultiLedgerDispute( } // Start Bob's watcher. + //nolint:contextcheck go func() { errs <- chBobAlice.Watch(bob) }() // Wait until watcher is active. - time.Sleep(100 * time.Millisecond) //nolint:gomnd // The 100ms is a guess on how long the watcher needs to setup. + time.Sleep(100 * time.Millisecond) //nolint:mnd // The 100ms is a guess on how long the watcher needs to setup. // Notify Bob when an update is complete. done := make(chan struct{}, 1) @@ -119,7 +122,7 @@ func TestMultiLedgerDispute( // Wait until Bob's watcher processed the update. <-done - time.Sleep(100 * time.Millisecond) //nolint:gomnd // The 100ms is a guess on how long the watcher needs to catch up. + time.Sleep(100 * time.Millisecond) //nolint:mnd // The 100ms is a guess on how long the watcher needs to catch up. // Alice registers state on L1 adjudicator. req1 := client.NewTestChannel(chAliceBob).AdjudicatorReq() diff --git a/client/test/multiledger_happy.go b/client/test/multiledger_happy.go index 36375428e..2aa0be4da 100644 --- a/client/test/multiledger_happy.go +++ b/client/test/multiledger_happy.go @@ -57,10 +57,12 @@ func TestMultiLedgerHappy(ctx context.Context, t *testing.T, mlt MultiLedgerSetu // Setup proposal handler. channels := make(chan *client.Channel, 1) errs := make(chan error) + //nolint:contextcheck // This is a test. go alice.Handle( AlwaysRejectChannelHandler(ctx, errs), AlwaysAcceptUpdateHandler(ctx, errs), ) + //nolint:contextcheck // This is a test. go bob.Handle( AlwaysAcceptChannelHandler(ctx, bob.WalletAddress, channels, errs), AlwaysAcceptUpdateHandler(ctx, errs), diff --git a/client/test/paymentchannel.go b/client/test/paymentchannel.go new file mode 100644 index 000000000..72897439c --- /dev/null +++ b/client/test/paymentchannel.go @@ -0,0 +1,254 @@ +// 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + "context" + "math/big" + "math/rand" + "testing" + "time" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "perun.network/go-perun/channel" + "perun.network/go-perun/client" + "perun.network/go-perun/wallet" + "perun.network/go-perun/wire" +) + +// PaymentChannelSetup contains the setup for a payment channel test. +type PaymentChannelSetup struct { + Clients [2]RoleSetup + ChallengeDuration uint64 + Asset channel.Asset + Balances PaymentChannelBalances + BalanceDelta channel.Bal + Rng *rand.Rand + WaitWatcherTimeout time.Duration + IsUTXO bool +} + +// PaymentChannelBalances contains a description of the balances that will be +// used during a virtual channel test. +type PaymentChannelBalances struct { + InitBalsAliceBob []*big.Int + BalsUpdated []*big.Int + FinalBals []*big.Int +} + +type paymentChannelTest struct { + alice *Client + bob *Client + chAliceBob *client.Channel + chBobAlice *client.Channel + balsUpdated []*big.Int + initBalsAlice *big.Int + initBalsBob *big.Int + finalBalsAlice *big.Int + finalBalsBob *big.Int + errs chan error + asset channel.Asset + balancesBefore channel.Balances + isUTXO bool +} + +// TestPaymentChannelOptimistic tests payment channel functionality in the happy case. +func TestPaymentChannelOptimistic( //nolint:revive // test.Test... stutters but OK here. + ctx context.Context, + t *testing.T, + setup PaymentChannelSetup, +) { + pct := setupPaymentChannelTest(t, ctx, setup) + assert := assert.New(t) + + err := pct.chAliceBob.Update(ctx, func(s *channel.State) { + s.IsFinal = true + }) + assert.NoError(err, "update final state") + + isSecondary := false + + // Settle the channels in a random order. + chs := []*client.Channel{pct.chAliceBob, pct.chBobAlice} + perm := rand.Perm(len(chs)) + t.Logf("Settle order = %v", perm) + for _, i := range perm { + err := chs[i].Settle(ctx, isSecondary) + isSecondary = true + + assert.NoErrorf(err, "settle channel: %d", i) + } + + // Check final balances. + balancesAfter := channel.Balances{ + { + pct.alice.BalanceReader.Balance(pct.asset), + pct.bob.BalanceReader.Balance(pct.asset), + }, + } + + balancesDiff := balancesAfter.Sub(pct.balancesBefore) + expectedBalancesDiff := channel.Balances{ + { + new(big.Int).Sub(pct.finalBalsAlice, pct.initBalsAlice), + new(big.Int).Sub(pct.finalBalsBob, pct.initBalsBob), + }, + } + balanceDelta := setup.BalanceDelta + eq := EqualBalancesWithDelta(expectedBalancesDiff, balancesDiff, balanceDelta) + assert.Truef(eq, "final ledger balances incorrect: expected balance difference %v +- %v, got %v", expectedBalancesDiff, balanceDelta, balancesDiff) +} + +// TestPaymentChannelDispute tests payment channel functionality in the dispute case. +func TestPaymentChannelDispute( //nolint:revive // test.Test... stutters but OK here. { + ctx context.Context, + t *testing.T, + setup PaymentChannelSetup, +) { + pct := setupPaymentChannelTest(t, ctx, setup) + assert := assert.New(t) + waitTimeout := setup.WaitWatcherTimeout + chs := []*client.Channel{pct.chAliceBob, pct.chBobAlice} + // Register the channels in a random order. + perm := rand.Perm(len(chs)) + t.Logf("perm = %v", perm) + for _, i := range perm { + err := client.NewTestChannel(chs[i]).Register(ctx) + assert.NoErrorf(err, "register channel: %d", i) + time.Sleep(waitTimeout) // Sleep to ensure that events have been processed and local client states have been updated. + } + + // Settle the channels in a random order. + isSecondary := false + perm = rand.Perm(len(chs)) + t.Logf("Settle order = %v", perm) + for _, i := range perm { + err := chs[i].Settle(ctx, isSecondary) + isSecondary = true + assert.NoErrorf(err, "settle channel: %d", i) + } + + // Check final balances. + balancesAfter := channel.Balances{ + { + pct.alice.BalanceReader.Balance(pct.asset), + pct.bob.BalanceReader.Balance(pct.asset), + }, + } + + balancesDiff := balancesAfter.Sub(pct.balancesBefore) + expectedBalancesDiff := channel.Balances{ + { + new(big.Int).Sub(pct.finalBalsAlice, pct.initBalsAlice), + new(big.Int).Sub(pct.finalBalsBob, pct.initBalsBob), + }, + } + balanceDelta := setup.BalanceDelta + eq := EqualBalancesWithDelta(expectedBalancesDiff, balancesDiff, balanceDelta) + assert.Truef(eq, "final ledger balances incorrect: expected balance difference %v +- %v, got %v", expectedBalancesDiff, balanceDelta, balancesDiff) +} + +func setupPaymentChannelTest( + t *testing.T, + ctx context.Context, + setup PaymentChannelSetup, +) (pct paymentChannelTest) { + t.Helper() + + // Set test values. + asset := setup.Asset + pct.asset = asset + pct.initBalsAlice = setup.Balances.InitBalsAliceBob[0] + pct.initBalsBob = setup.Balances.InitBalsAliceBob[1] + pct.balsUpdated = setup.Balances.BalsUpdated + pct.finalBalsAlice = setup.Balances.FinalBals[0] + pct.finalBalsBob = setup.Balances.FinalBals[1] + pct.isUTXO = setup.IsUTXO + + const errBufferLen = 10 + pct.errs = make(chan error, errBufferLen) + + // Setup clients. + roles := setup.Clients + clients := NewClients(t, setup.Rng, roles[:]) + alice, bob := clients[0], clients[1] + pct.alice, pct.bob = alice, bob + + // Store client balances before running test. + pct.balancesBefore = channel.Balances{ + { + pct.alice.BalanceReader.Balance(pct.asset), + pct.bob.BalanceReader.Balance(pct.asset), + }, + } + + // Setup Bob's proposal and update handler. + channelsBob := make(chan *client.Channel, 1) + var openingProposalHandlerBob client.ProposalHandlerFunc = func(cp client.ChannelProposal, pr *client.ProposalResponder) { + switch cp := cp.(type) { + case *client.LedgerChannelProposalMsg: + ch, err := pr.Accept(ctx, cp.Accept(bob.WalletAddress, client.WithRandomNonce())) + if err != nil { + pct.errs <- errors.WithMessage(err, "accepting ledger channel proposal") + } + channelsBob <- ch + default: + pct.errs <- errors.Errorf("invalid channel proposal: %v", cp) + } + } + var updateProposalHandlerBob client.UpdateHandlerFunc = func( + s *channel.State, cu client.ChannelUpdate, ur *client.UpdateResponder, + ) { + err := ur.Accept(ctx) + if err != nil { + pct.errs <- errors.WithMessage(err, "Bob: accepting channel update") + } + } + go bob.Handle(openingProposalHandlerBob, updateProposalHandlerBob) //nolint:contextcheck + + // Establish ledger channel between Alice and Ingrid. + peersAlice := []map[wallet.BackendID]wire.Address{wire.AddressMapfromAccountMap(alice.Identity), wire.AddressMapfromAccountMap(bob.Identity)} + var bID wallet.BackendID + for i := range peersAlice[0] { + bID = i + break + } + initAllocAlice := channel.NewAllocation(len(peersAlice), []wallet.BackendID{bID}, asset) + initAllocAlice.SetAssetBalances(asset, []channel.Bal{pct.initBalsAlice, pct.initBalsBob}) + lcpAlice, err := client.NewLedgerChannelProposal( + setup.ChallengeDuration, + alice.WalletAddress, + initAllocAlice, + peersAlice, + ) + require.NoError(t, err, "creating ledger channel proposal") + + pct.chAliceBob, err = alice.ProposeChannel(ctx, lcpAlice) + require.NoError(t, err, "opening channel between Alice and Ingrid") + select { + case pct.chBobAlice = <-channelsBob: + case err := <-pct.errs: + t.Fatalf("Error in go-routine: %v", err) + } + + err = pct.chAliceBob.Update(ctx, func(s *channel.State) { + s.Balances = channel.Balances{pct.balsUpdated} + }) + require.NoError(t, err, "updating virtual channel") + + return pct +} diff --git a/client/test/persistence.go b/client/test/persistence.go index b80c93c28..4ecd00b98 100644 --- a/client/test/persistence.go +++ b/client/test/persistence.go @@ -195,6 +195,11 @@ func (r *Robert) Execute(cfg ExecConfig) { r.RequireNoError(r.Close()) } +// Errors returns the error channel. +func (r *multiClientRole) Errors() <-chan error { + return r.errs +} + func (r *multiClientRole) assertPersistedPeerAndChannel(cfg ExecConfig, state *channel.State) { _, them := r.Idxs(cfg.Peers()) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -212,12 +217,7 @@ func (r *multiClientRole) assertPersistedPeerAndChannel(cfg ExecConfig, state *c restoredCh := chIt.Channel() r.RequireNoError(chIt.Close()) r.RequireTrue(restoredCh.ID() == state.ID) - r.RequireNoError(restoredCh.CurrentTXV.State.Equal(state)) -} - -// Errors returns the error channel. -func (r *multiClientRole) Errors() <-chan error { - return r.errs + r.RequireNoError(restoredCh.CurrentTXV.Equal(state)) } type addresses []map[wallet.BackendID]wire.Address diff --git a/client/test/progression.go b/client/test/progression.go index be498dd9c..bfe728868 100644 --- a/client/test/progression.go +++ b/client/test/progression.go @@ -80,7 +80,7 @@ func (r *Paul) Execute(cfg ExecConfig) { r.Proposer.Execute(cfg, r.exec) } -func (r *Paul) exec(_cfg ExecConfig, ch *paymentChannel) { +func (r *Paul) exec(_ ExecConfig, ch *paymentChannel) { ctx := r.Ctx() assetIdx := 0 @@ -98,7 +98,7 @@ func (r *Paul) exec(_cfg ExecConfig, ch *paymentChannel) { bal := func(user channel.Index) int64 { return s.Balances[assetIdx][user].Int64() } - half := (bal(0) + bal(1)) / 2 //nolint:gomnd + half := (bal(0) + bal(1)) / 2 //nolint:mnd s.Balances[assetIdx][0] = big.NewInt(half) s.Balances[assetIdx][1] = big.NewInt(half) })) @@ -112,7 +112,7 @@ func (r *Paul) exec(_cfg ExecConfig, ch *paymentChannel) { // Await progressed event 2. r.log.Debugf("%v awaiting progressed event 2", r.setup.Name) e = <-r.progressed - r.RequireTruef(e.Version() == 2, "expected version 2, got version %v", e.Version()) //nolint:gomnd + r.RequireTruef(e.Version() == 2, "expected version 2, got version %v", e.Version()) //nolint:mnd r.waitStage() // withdraw @@ -166,7 +166,7 @@ func (r *Paula) exec(_cfg ExecConfig, ch *paymentChannel, _ *acceptNextPropHandl bal := func(user channel.Index) int64 { return s.Balances[assetIdx][user].Int64() } - half := (bal(0) + bal(1)) / 2 //nolint:gomnd + half := (bal(0) + bal(1)) / 2 //nolint:mnd s.Balances[assetIdx][0] = big.NewInt(half + paulPaulaBalTransferAmount) s.Balances[assetIdx][1] = big.NewInt(half - paulPaulaBalTransferAmount) })) @@ -174,7 +174,7 @@ func (r *Paula) exec(_cfg ExecConfig, ch *paymentChannel, _ *acceptNextPropHandl // Await progressed event 2. r.log.Debugf("%v awaiting progressed event 2", r.setup.Name) e = <-r.progressed - r.RequireTruef(e.Version() == 2, "expected version 2, got version %v", e.Version()) //nolint:gomnd + r.RequireTruef(e.Version() == 2, "expected version 2, got version %v", e.Version()) //nolint:mnd r.waitStage() // await ready to conclude diff --git a/client/test/proposalmsgs.go b/client/test/proposalmsgs.go index 840c3d99e..39efd718b 100644 --- a/client/test/proposalmsgs.go +++ b/client/test/proposalmsgs.go @@ -40,7 +40,7 @@ func ProposalMsgsSerializationTest(t *testing.T, serializerTest func(t *testing. func channelProposalReqSerializationTest(t *testing.T, serializerTest func(t *testing.T, msg wire.Msg)) { t.Helper() rng := pkgtest.Prng(t) - for i := 0; i < 16; i++ { + for i := range 16 { var ( app client.ProposalOpts m wire.Msg @@ -55,7 +55,7 @@ func channelProposalReqSerializationTest(t *testing.T, serializerTest func(t *te case 1: m, err = NewRandomSubChannelProposal(rng, client.WithNonceFrom(rng), app) require.NoError(t, err) - case 2: //nolint: gomnd // This is not a magic number. + case 2: //nolint: mnd // This is not a magic number. m, err = NewRandomVirtualChannelProposal(rng, client.WithNonceFrom(rng), app) require.NoError(t, err) } @@ -67,14 +67,14 @@ func channelProposalAccSerializationTest(t *testing.T, serializerTest func(t *te t.Helper() rng := pkgtest.Prng(t) t.Run("ledger channel", func(t *testing.T) { - for i := 0; i < 16; i++ { + for range 16 { proposal := NewRandomLedgerChannelProposal(rng) m := proposal.Accept(wallettest.NewRandomAddresses(rng, channel.TestBackendID), client.WithNonceFrom(rng)) serializerTest(t, m) } }) t.Run("sub channel", func(t *testing.T) { - for i := 0; i < 16; i++ { + for range 16 { var err error proposal, err := NewRandomSubChannelProposal(rng) require.NoError(t, err) @@ -83,7 +83,7 @@ func channelProposalAccSerializationTest(t *testing.T, serializerTest func(t *te } }) t.Run("virtual channel", func(t *testing.T) { - for i := 0; i < 16; i++ { + for range 16 { var err error proposal, err := NewRandomVirtualChannelProposal(rng) require.NoError(t, err) @@ -98,7 +98,7 @@ func channelProposalRejSerializationTest(t *testing.T, serializerTest func(t *te minLen := 16 maxLenDiff := 16 rng := pkgtest.Prng(t) - for i := 0; i < 16; i++ { + for range 16 { m := &client.ChannelProposalRejMsg{ ProposalID: newRandomProposalID(rng), Reason: newRandomASCIIString(rng, minLen, maxLenDiff), diff --git a/client/test/role.go b/client/test/role.go index 2791c3b1e..9f74a92c6 100644 --- a/client/test/role.go +++ b/client/test/role.go @@ -28,7 +28,7 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/channel" "perun.network/go-perun/channel/persistence" "perun.network/go-perun/client" @@ -134,7 +134,7 @@ func NewClients(t *testing.T, rng *rand.Rand, setups []RoleSetup) []*Client { setupWallet[i] = w } cl, err := client.New(wire.AddressMapfromAccountMap(setup.Identity), setup.Bus, setup.Funder, setup.Adjudicator, setupWallet, setup.Watcher) - assert.NoError(t, err) + require.NoError(t, err) walletAddress := make(map[wallet.BackendID]wallet.Address) for i, w := range setup.Wallet { walletAddress[i] = w.NewRandomAccount(rng).Address() @@ -160,7 +160,7 @@ func ExecuteTwoPartyTest(ctx context.Context, t *testing.T, role [2]Executer, cf var wg pkgsync.WaitGroup // start clients - for i := 0; i < len(role); i++ { + for i := range role { wg.Add(1) go func(i int) { log.Infof("Executing role %d", i) @@ -224,59 +224,6 @@ func (c *BaseExecConfig) App() client.ProposalOpts { return c.app } -// makeRole creates a client for the given setup and wraps it into a Role. -func makeRole(t *testing.T, setup RoleSetup, numStages int) (r role) { - t.Helper() - r = role{ - chans: &channelMap{entries: make(map[channel.ID]*paymentChannel)}, - setup: setup, - timeout: setup.Timeout, - errs: setup.Errors, - numStages: numStages, - challengeDuration: setup.ChallengeDuration, - } - setupWallet := make(map[wallet.BackendID]wallet.Wallet) - for i, w := range r.setup.Wallet { - setupWallet[i] = w - } - cl, err := client.New(wire.AddressMapfromAccountMap(r.setup.Identity), - r.setup.Bus, r.setup.Funder, r.setup.Adjudicator, setupWallet, r.setup.Watcher) - if err != nil { - t.Fatal("Error creating client: ", err) - } - r.setClient(cl) // init client - return r -} - -func (r *role) setClient(cl *client.Client) { - if r.setup.PR != nil { - cl.EnablePersistence(r.setup.PR) - } - cl.OnNewChannel(func(_ch *client.Channel) { - ch := newPaymentChannel(_ch, r) - r.chans.add(ch) - if r.newChan != nil { - r.newChan(ch) // forward callback - } - }) - r.Client = cl - // Append role field to client logger and set role logger to client logger. - r.log = log.AppendField(cl, "role", r.setup.Name) -} - -func (chs *channelMap) channel(ch channel.ID) (_ch *paymentChannel, ok bool) { - chs.RLock() - defer chs.RUnlock() - _ch, ok = chs.entries[ch] - return -} - -func (chs *channelMap) add(ch *paymentChannel) { - chs.Lock() - defer chs.Unlock() - chs.entries[ch.ID()] = ch -} - func (r *role) OnNewChannel(callback func(ch *paymentChannel)) { r.newChan = callback } @@ -307,15 +254,6 @@ func (r *role) SetStages(st Stages) { } } -func (r *role) waitStage() { - if r.stages != nil { - r.numStages-- - stage := &r.stages[r.numStages] - stage.Done() - stage.Wait() - } -} - // Idxs maps the passed addresses to the indices in the 2-party-channel. If the // setup's Identity is not found in peers, Idxs panics. func (r *role) Idxs(peers [2]map[wallet.BackendID]wire.Address) (our, their channel.Index) { @@ -358,7 +296,7 @@ func (r *role) RequireNoErrorf(err error, msg string, args ...interface{}) { func (r *role) RequireTrue(b bool) { if !b { - r.errs <- fmt.Errorf("expected true, got false") + r.errs <- errors.New("expected true, got false") } } @@ -457,14 +395,6 @@ func (r *role) SubChannelProposal( return prop } -func (r *role) acceptNextPropHandler(rng *rand.Rand) *acceptNextPropHandler { - return &acceptNextPropHandler{ - r: r, - props: make(chan proposalAndResponder), - rng: rng, - } -} - func (h *acceptNextPropHandler) HandleProposal(prop client.ChannelProposal, res *client.ProposalResponder) { select { case h.props <- proposalAndResponder{prop, res}: @@ -530,3 +460,73 @@ func (h *roleUpdateHandler) HandleUpdate(_ *channel.State, up client.ChannelUpda (*role)(h).RequireTruef(ok, "unknown channel: %v", up.State.ID) ch.Handle(up, res) } + +// makeRole creates a client for the given setup and wraps it into a Role. +func makeRole(t *testing.T, setup RoleSetup, numStages int) (r role) { + t.Helper() + r = role{ + chans: &channelMap{entries: make(map[channel.ID]*paymentChannel)}, + setup: setup, + timeout: setup.Timeout, + errs: setup.Errors, + numStages: numStages, + challengeDuration: setup.ChallengeDuration, + } + setupWallet := make(map[wallet.BackendID]wallet.Wallet) + for i, w := range r.setup.Wallet { + setupWallet[i] = w + } + cl, err := client.New(wire.AddressMapfromAccountMap(r.setup.Identity), + r.setup.Bus, r.setup.Funder, r.setup.Adjudicator, setupWallet, r.setup.Watcher) + if err != nil { + t.Fatal("Error creating client: ", err) + } + r.setClient(cl) // init client + return r +} + +func (r *role) setClient(cl *client.Client) { + if r.setup.PR != nil { + cl.EnablePersistence(r.setup.PR) + } + cl.OnNewChannel(func(_ch *client.Channel) { + ch := newPaymentChannel(_ch, r) + r.chans.add(ch) + if r.newChan != nil { + r.newChan(ch) // forward callback + } + }) + r.Client = cl + // Append role field to client logger and set role logger to client logger. + r.log = log.AppendField(cl, "role", r.setup.Name) +} + +func (chs *channelMap) channel(ch channel.ID) (_ch *paymentChannel, ok bool) { + chs.RLock() + defer chs.RUnlock() + _ch, ok = chs.entries[ch] + return +} + +func (chs *channelMap) add(ch *paymentChannel) { + chs.Lock() + defer chs.Unlock() + chs.entries[ch.ID()] = ch +} + +func (r *role) acceptNextPropHandler(rng *rand.Rand) *acceptNextPropHandler { + return &acceptNextPropHandler{ + r: r, + props: make(chan proposalAndResponder), + rng: rng, + } +} + +func (r *role) waitStage() { + if r.stages != nil { + r.numStages-- + stage := &r.stages[r.numStages] + stage.Done() + stage.Wait() + } +} diff --git a/client/test/subchannel.go b/client/test/subchannel.go index 061840fa6..782489a4c 100644 --- a/client/test/subchannel.go +++ b/client/test/subchannel.go @@ -34,8 +34,8 @@ type SusieTimExecConfig struct { // NewSusieTimExecConfig creates a new object from the given parameters. func NewSusieTimExecConfig( base BaseExecConfig, - numSubChannels int, - numSubSubChannels int, + _ int, + _ int, subChannelFunds [][2]*big.Int, subSubChannelFunds [][2]*big.Int, leafChannelApp client.ProposalOpts, @@ -81,13 +81,13 @@ func (r *Susie) exec(_cfg ExecConfig, ledgerChannel *paymentChannel) { } var subChannels []*paymentChannel - for i := 0; i < len(cfg.SubChannelFunds); i++ { + for i := range len(cfg.SubChannelFunds) { c := openSubChannel(ledgerChannel, cfg.SubChannelFunds[i][:], cfg.App()) subChannels = append(subChannels, c) } var subSubChannels []*paymentChannel - for i := 0; i < len(cfg.SubSubChannelFunds); i++ { + for i := range len(cfg.SubSubChannelFunds) { c := openSubChannel(subChannels[0], cfg.SubSubChannelFunds[i][:], cfg.LeafChannelApp) subSubChannels = append(subSubChannels, c) } @@ -175,13 +175,13 @@ func (r *Tim) exec(_cfg ExecConfig, ledgerChannel *paymentChannel, propHandler * } var subChannels []*paymentChannel - for i := 0; i < len(cfg.SubChannelFunds); i++ { + for i := range len(cfg.SubChannelFunds) { c := acceptNext(ledgerChannel, cfg.SubChannelFunds[i][:]) subChannels = append(subChannels, c) } var subSubChannels []*paymentChannel - for i := 0; i < len(cfg.SubSubChannelFunds); i++ { + for i := range len(cfg.SubSubChannelFunds) { c := acceptNext(subChannels[0], cfg.SubSubChannelFunds[i][:]) subSubChannels = append(subSubChannels, c) } diff --git a/client/test/subchannel_dispute.go b/client/test/subchannel_dispute.go index 754a885e5..45692d66a 100644 --- a/client/test/subchannel_dispute.go +++ b/client/test/subchannel_dispute.go @@ -105,7 +105,7 @@ func (r *DisputeSusie) exec(_cfg ExecConfig, ledgerChannel *paymentChannel) { r.log.Debug("Attempt withdrawing refuted state.") m := channel.MakeStateMap() - m.Add(subState0.State) + m.Add(&subState0) err = r.setup.Adjudicator.Withdraw(ctx, reqLedger, m) r.RequireTruef(err != nil, "withdraw should fail because other party should have refuted.") @@ -124,6 +124,15 @@ type DisputeTim struct { subCh channel.ID } +// NewDisputeTim creates a new Responder that executes the DisputeTim protocol. +func NewDisputeTim(t *testing.T, setup RoleSetup) *DisputeTim { + t.Helper() + return &DisputeTim{ + Responder: *NewResponder(t, setup, nStagesDisputeSusieTime), + registered: make(chan *channel.RegisteredEvent), + } +} + // time to wait until a parent channel watcher becomes active. const channelWatcherWait = 100 * time.Millisecond @@ -135,15 +144,6 @@ func (r *DisputeTim) HandleAdjudicatorEvent(e channel.AdjudicatorEvent) { } } -// NewDisputeTim creates a new Responder that executes the DisputeTim protocol. -func NewDisputeTim(t *testing.T, setup RoleSetup) *DisputeTim { - t.Helper() - return &DisputeTim{ - Responder: *NewResponder(t, setup, nStagesDisputeSusieTime), - registered: make(chan *channel.RegisteredEvent), - } -} - // Execute executes the DisputeTim protocol. func (r *DisputeTim) Execute(cfg ExecConfig) { r.Responder.Execute(cfg, r.exec) diff --git a/client/test/syncmsgs.go b/client/test/syncmsgs.go index 4d9e87063..77c256111 100644 --- a/client/test/syncmsgs.go +++ b/client/test/syncmsgs.go @@ -15,6 +15,7 @@ package test import ( + "math" "testing" "perun.network/go-perun/channel" @@ -28,10 +29,14 @@ import ( func ChannelSyncMsgSerializationTest(t *testing.T, serializerTest func(t *testing.T, msg wire.Msg)) { t.Helper() rng := pkgtest.Prng(t) - for i := 0; i < 4; i++ { + for range 4 { state := test.NewRandomState(rng) + phase := rng.Intn(channel.LastPhase) + if phase < 0 || phase > math.MaxUint8 { + panic("LastPhase is too large") + } m := &client.ChannelSyncMsg{ - Phase: channel.Phase(rng.Intn(channel.LastPhase)), + Phase: channel.Phase(phase), CurrentTX: channel.Transaction{ State: state, Sigs: newRandomSigs(rng, state.NumParts()), diff --git a/client/test/updatemsgs.go b/client/test/updatemsgs.go index e1a4e1332..deeaa8bd0 100644 --- a/client/test/updatemsgs.go +++ b/client/test/updatemsgs.go @@ -15,6 +15,7 @@ package test import ( + "math" "math/rand" "testing" @@ -41,7 +42,7 @@ func channelUpdateSerializationTest(t *testing.T, serializerTest func(t *testing ) { t.Helper() rng := pkgtest.Prng(t) - for i := 0; i < 4; i++ { + for range 4 { m := newRandomMsgChannelUpdate(rng) serializerTest(t, m) } @@ -53,7 +54,7 @@ func virtualChannelFundingProposalSerializationTest( ) { t.Helper() rng := pkgtest.Prng(t) - for i := 0; i < 4; i++ { + for range 4 { msgUp := newRandomMsgChannelUpdate(rng) params, state := test.NewRandomParamsAndState(rng) m := &client.VirtualChannelFundingProposalMsg{ @@ -75,7 +76,7 @@ func virtualChannelSettlementProposalSerializationTest( ) { t.Helper() rng := pkgtest.Prng(t) - for i := 0; i < 4; i++ { + for range 4 { msgUp := newRandomMsgChannelUpdate(rng) params, state := test.NewRandomParamsAndState(rng) m := &client.VirtualChannelSettlementProposalMsg{ @@ -93,11 +94,11 @@ func virtualChannelSettlementProposalSerializationTest( func channelUpdateAccSerializationTest(t *testing.T, serializerTest func(t *testing.T, msg wire.Msg)) { t.Helper() rng := pkgtest.Prng(t) - for i := 0; i < 4; i++ { + for range 4 { sig := newRandomSig(rng, channel.TestBackendID) m := &client.ChannelUpdateAccMsg{ ChannelID: test.NewRandomChannelID(rng), - Version: uint64(rng.Int63()), + Version: rng.Uint64(), Sig: sig, } serializerTest(t, m) @@ -109,10 +110,10 @@ func channelUpdateRejSerializationTest(t *testing.T, serializerTest func(t *test rng := pkgtest.Prng(t) minLen := 16 maxLenDiff := 16 - for i := 0; i < 4; i++ { + for range 4 { m := &client.ChannelUpdateRejMsg{ ChannelID: test.NewRandomChannelID(rng), - Version: uint64(rng.Int63()), + Version: rng.Uint64(), Reason: newRandomASCIIString(rng, minLen, maxLenDiff), } serializerTest(t, m) @@ -122,10 +123,14 @@ func channelUpdateRejSerializationTest(t *testing.T, serializerTest func(t *test func newRandomMsgChannelUpdate(rng *rand.Rand) *client.ChannelUpdateMsg { state := test.NewRandomState(rng) sig := newRandomSig(rng, channel.TestBackendID) + idx := rng.Intn(state.NumParts()) + if idx < 0 || idx > math.MaxUint16 { + panic("index out of bounds") + } return &client.ChannelUpdateMsg{ ChannelUpdate: client.ChannelUpdate{ State: state, - ActorIdx: channel.Index(rng.Intn(state.NumParts())), + ActorIdx: channel.Index(idx), }, Sig: sig, } diff --git a/client/test/virtualchannel.go b/client/test/virtualchannel.go index 6ceb86062..a9751e0b8 100644 --- a/client/test/virtualchannel.go +++ b/client/test/virtualchannel.go @@ -21,13 +21,12 @@ import ( "testing" "time" - "perun.network/go-perun/wallet" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "perun.network/go-perun/channel" "perun.network/go-perun/client" + "perun.network/go-perun/wallet" "perun.network/go-perun/wire" "polycry.pt/poly-go/sync" ) @@ -41,6 +40,7 @@ type VirtualChannelSetup struct { BalanceDelta channel.Bal Rng *rand.Rand WaitWatcherTimeout time.Duration + IsUTXO bool } // TestVirtualChannelOptimistic tests virtual channel functionality in the @@ -75,10 +75,56 @@ func TestVirtualChannelOptimistic( //nolint:revive // test.Test... stutters but } // Test final balances. - err := vct.chAliceIngrid.State().Balances.AssertEqual(channel.Balances{vct.finalBalsAlice}) + err := vct.chAliceIngrid.State().AssertEqual(channel.Balances{vct.finalBalsAlice}) assert.NoError(t, err, "Alice: invalid final balances") - err = vct.chBobIngrid.State().Balances.AssertEqual(channel.Balances{vct.finalBalsBob}) + err = vct.chBobIngrid.State().AssertEqual(channel.Balances{vct.finalBalsBob}) assert.NoError(t, err, "Bob: invalid final balances") + + // Close the parents. + err = vct.chIngridAlice.Update(ctx, func(s *channel.State) { + s.IsFinal = true + }) + assert.NoError(t, err, "Alice: close channel") + err = vct.chIngridBob.Update(ctx, func(s *channel.State) { + s.IsFinal = true + }) + assert.NoError(t, err, "Bob: close channel") + chs = []*client.Channel{vct.chAliceIngrid, vct.chIngridAlice, vct.chBobIngrid, vct.chIngridBob} + isSecondary := [2]bool{false, false} + perm := rand.Perm(len(chs)) + t.Logf("Settle order = %v", perm) + for _, i := range perm { + var err error + if i < 2 { //nolint:mnd + err = chs[i].Settle(ctx, isSecondary[0]) + isSecondary[0] = true + } else { + err = chs[i].Settle(ctx, isSecondary[1]) + isSecondary[1] = true + } + assert.NoErrorf(t, err, "settle channel: %d", i) + } + + // Check final balances. + balancesAfter := channel.Balances{ + { + vct.alice.BalanceReader.Balance(vct.asset), + vct.bob.BalanceReader.Balance(vct.asset), + vct.ingrid.BalanceReader.Balance(vct.asset), + }, + } + + balancesDiff := balancesAfter.Sub(vct.balancesBefore) + expectedBalancesDiff := channel.Balances{ + { + new(big.Int).Sub(vct.finalBalsAlice[0], vct.initBalsAlice[0]), + new(big.Int).Sub(vct.finalBalsBob[0], vct.initBalsBob[0]), + big.NewInt(0), + }, + } + balanceDelta := setup.BalanceDelta + eq := EqualBalancesWithDelta(expectedBalancesDiff, balancesDiff, balanceDelta) + assert.Truef(t, eq, "final ledger balances incorrect: expected balance difference %v +- %v, got %v", expectedBalancesDiff, balanceDelta, balancesDiff) } // TestVirtualChannelDispute tests virtual channel functionality in the dispute @@ -92,6 +138,8 @@ func TestVirtualChannelDispute( //nolint:revive // test.Test... stutters but OK assert := assert.New(t) waitTimeout := setup.WaitWatcherTimeout + time.Sleep(waitTimeout) // Sleep to ensure that events have been processed and local client states have been updated. + chs := []*client.Channel{vct.chAliceIngrid, vct.chIngridAlice, vct.chBobIngrid, vct.chIngridBob} // Register the channels in a random order. perm := rand.Perm(len(chs)) @@ -103,8 +151,18 @@ 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, false) + isSecondary := [2]bool{false, false} + perm = rand.Perm(len(chs)) + t.Logf("Settle order = %v", perm) + for _, i := range perm { + var err error + if i < 2 { //nolint:mnd + err = chs[i].Settle(ctx, isSecondary[0]) + isSecondary[0] = true + } else { + err = chs[i].Settle(ctx, isSecondary[1]) + isSecondary[1] = true + } assert.NoErrorf(err, "settle channel: %d", i) } @@ -149,6 +207,8 @@ type virtualChannelTest struct { errs chan error asset channel.Asset balancesBefore channel.Balances + isUTXO bool + parentIDs [2]channel.ID } // VirtualChannelBalances contains a description of the balances that will be @@ -162,7 +222,7 @@ type VirtualChannelBalances struct { FinalBalsBob []*big.Int } -func setupVirtualChannelTest( +func setupVirtualChannelTest( //nolint t *testing.T, ctx context.Context, setup VirtualChannelSetup, @@ -180,6 +240,7 @@ func setupVirtualChannelTest( vct.finalBalsAlice = setup.Balances.FinalBalsAlice vct.finalBalsBob = setup.Balances.FinalBalsBob vct.finalBalIngrid = new(big.Int).Add(vct.finalBalsAlice[1], vct.finalBalsBob[1]) + vct.isUTXO = setup.IsUTXO const errBufferLen = 10 vct.errs = make(chan error, errBufferLen) @@ -213,10 +274,10 @@ func setupVirtualChannelTest( } } var updateProposalHandlerIngrid client.UpdateHandlerFunc = func( - s *channel.State, cu client.ChannelUpdate, ur *client.UpdateResponder, + _ *channel.State, cu client.ChannelUpdate, ur *client.UpdateResponder, ) { } - go ingrid.Client.Handle(openingProposalHandlerIngrid, updateProposalHandlerIngrid) + go ingrid.Handle(openingProposalHandlerIngrid, updateProposalHandlerIngrid) //nolint:contextcheck // Establish ledger channel between Alice and Ingrid. peersAlice := []map[wallet.BackendID]wire.Address{wire.AddressMapfromAccountMap(alice.Identity), wire.AddressMapfromAccountMap(ingrid.Identity)} @@ -280,14 +341,40 @@ func setupVirtualChannelTest( } } var updateProposalHandlerBob client.UpdateHandlerFunc = func( - s *channel.State, cu client.ChannelUpdate, ur *client.UpdateResponder, + _ *channel.State, cu client.ChannelUpdate, ur *client.UpdateResponder, ) { err := ur.Accept(ctx) if err != nil { vct.errs <- errors.WithMessage(err, "Bob: accepting channel update") } } - go bob.Client.Handle(openingProposalHandlerBob, updateProposalHandlerBob) + go bob.Handle(openingProposalHandlerBob, updateProposalHandlerBob) //nolint:contextcheck + + // Setup Alice's handlers. + channelsAlice := make(chan *client.Channel, 1) + var openingProposalHandlerAlice client.ProposalHandlerFunc = func( + cp client.ChannelProposal, pr *client.ProposalResponder, + ) { + switch cp := cp.(type) { + case *client.VirtualChannelProposalMsg: + ch, err := pr.Accept(ctx, cp.Accept(bob.WalletAddress)) + if err != nil { + vct.errs <- errors.WithMessage(err, "accepting virtual channel proposal") + } + channelsAlice <- ch + default: + vct.errs <- errors.Errorf("invalid channel proposal: %v", cp) + } + } + var updateProposalHandlerAlice client.UpdateHandlerFunc = func( + s *channel.State, cu client.ChannelUpdate, ur *client.UpdateResponder, + ) { + err := ur.Accept(ctx) + if err != nil { + vct.errs <- errors.WithMessage(err, "Alice: accepting channel update") + } + } + go alice.Handle(openingProposalHandlerAlice, updateProposalHandlerAlice) //nolint:contextcheck // Establish virtual channel between Alice and Bob via Ingrid. initAllocVirtual := channel.Allocation{ @@ -297,14 +384,37 @@ func setupVirtualChannelTest( } indexMapAlice := []channel.Index{0, 1} indexMapBob := []channel.Index{1, 0} - vcp, err := client.NewVirtualChannelProposal( - setup.ChallengeDuration, - alice.WalletAddress, - &initAllocVirtual, - []map[wallet.BackendID]wire.Address{wire.AddressMapfromAccountMap(alice.Identity), wire.AddressMapfromAccountMap(bob.Identity)}, - []channel.ID{vct.chAliceIngrid.ID(), vct.chBobIngrid.ID()}, - [][]channel.Index{indexMapAlice, indexMapBob}, - ) + + vct.parentIDs[0] = vct.chAliceIngrid.ID() + vct.parentIDs[1] = vct.chBobIngrid.ID() + + var vcp *client.VirtualChannelProposalMsg + if setup.IsUTXO { + // UTXO Chains need additional auxiliary data to be able to + // create a virtual channel. + var aux channel.Aux + copy(aux[:channel.IDLen], vct.parentIDs[0][:]) + copy(aux[channel.IDLen:], vct.parentIDs[1][:]) + + vcp, err = client.NewVirtualChannelProposal( + setup.ChallengeDuration, + alice.WalletAddress, + &initAllocVirtual, + []map[wallet.BackendID]wire.Address{wire.AddressMapfromAccountMap(alice.Identity), wire.AddressMapfromAccountMap(bob.Identity)}, + []channel.ID{vct.chAliceIngrid.ID(), vct.chBobIngrid.ID()}, + [][]channel.Index{indexMapAlice, indexMapBob}, + client.WithAux(aux), + ) + } else { + vcp, err = client.NewVirtualChannelProposal( + setup.ChallengeDuration, + alice.WalletAddress, + &initAllocVirtual, + []map[wallet.BackendID]wire.Address{wire.AddressMapfromAccountMap(alice.Identity), wire.AddressMapfromAccountMap(bob.Identity)}, + []channel.ID{vct.chAliceIngrid.ID(), vct.chBobIngrid.ID()}, + [][]channel.Index{indexMapAlice, indexMapBob}, + ) + } require.NoError(err, "creating virtual channel proposal") vct.chAliceBob, err = alice.ProposeChannel(ctx, vcp) diff --git a/client/testchannel.go b/client/testchannel.go index 3a56af781..8f4e785cc 100644 --- a/client/testchannel.go +++ b/client/testchannel.go @@ -40,5 +40,5 @@ func (c *TestChannel) AdjudicatorReq() channel.AdjudicatorReq { // Register exposes dispute registration. func (c *TestChannel) Register(ctx context.Context) error { - return c.Channel.registerDispute(ctx) + return c.registerDispute(ctx) } diff --git a/client/update.go b/client/update.go index f75efa0ee..2087d97f6 100644 --- a/client/update.go +++ b/client/update.go @@ -16,7 +16,6 @@ package client import ( "context" - "fmt" "github.com/pkg/errors" @@ -49,7 +48,7 @@ func (c *Client) cacheVersion1Update(uh UpdateHandler, p map[wallet.BackendID]wi c.version1Cache.mu.Lock() defer c.version1Cache.mu.Unlock() - if !(m.Base().State.Version == 1 && c.version1Cache.enabled > 0) { + if m.Base().State.Version != 1 || c.version1Cache.enabled <= 0 { return false } @@ -119,7 +118,7 @@ func (r *UpdateResponder) Accept(ctx context.Context) error { return errors.New("context must not be nil") } if !r.called.TrySet() { - return fmt.Errorf("multiple calls on channel update responder") + return errors.New("multiple calls on channel update responder") } return r.channel.acceptUpdate(ctx, r.pidx, r.req) @@ -135,7 +134,7 @@ func (r *UpdateResponder) Reject(ctx context.Context, reason string) error { return errors.New("context must not be nil") } if !r.called.TrySet() { - return fmt.Errorf("multiple calls on channel update responder") + return errors.New("multiple calls on channel update responder") } return r.channel.rejectUpdate(ctx, r.pidx, r.req, reason) diff --git a/client/virtual_channel.go b/client/virtual_channel.go index c42feb9c0..2826cbe71 100644 --- a/client/virtual_channel.go +++ b/client/virtual_channel.go @@ -17,6 +17,7 @@ package client import ( "context" "fmt" + "math" "time" "github.com/pkg/errors" @@ -60,7 +61,7 @@ func (c *Channel) proposeVirtualChannelFunding(ctx context.Context, virtual *Cha // Deposit initial balances into sub-allocation balances := virtual.translateBalances(indexMap) - state.Allocation.Balances = state.Allocation.Balances.Sub(balances) + state.Balances = state.Sub(balances) state.AddSubAlloc(*channel.NewSubAlloc(virtual.ID(), balances.Sum(), indexMap)) err := c.updateGeneric(ctx, state, func(mcu *ChannelUpdateMsg) wire.Msg { @@ -185,6 +186,9 @@ func (c *Client) persistVirtualChannel(ctx context.Context, parent *Channel, pee } for i, sig := range sigs { + if i < 0 || i > math.MaxUint16 { + return nil, errors.Errorf("index out of bounds: %d", i) + } err = ch.machine.AddSig(ctx, channel.Index(i), sig) if err != nil { return nil, err @@ -223,6 +227,9 @@ func (c *Channel) pushVirtualUpdate(ctx context.Context, state *channel.State, s } for i, sig := range sigs { + if i < 0 || i > math.MaxUint16 { + return errors.Errorf("index out of bounds: %d", i) + } idx := channel.Index(i) if err := m.AddSig(ctx, idx, sig); err != nil { return err @@ -238,7 +245,6 @@ func (c *Channel) pushVirtualUpdate(ctx context.Context, state *channel.State, s return err } -//nolint:funlen func (c *Client) validateVirtualChannelFundingProposal( ch *Channel, prop *VirtualChannelFundingProposalMsg, @@ -300,7 +306,7 @@ func (c *Client) validateVirtualChannelFundingProposal( // Assert sufficient funds in parent channel. virtual := transformBalances(prop.Initial.State.Balances, ch.state().NumParts(), subAlloc.IndexMap) - if err := ch.state().Balances.AssertGreaterOrEqual(virtual); err != nil { + if err := ch.state().AssertGreaterOrEqual(virtual); err != nil { return errors.WithMessage(err, "insufficient funds") } @@ -359,6 +365,7 @@ func (c *Client) matchFundingProposal(ctx context.Context, a, b interface{}) boo return false } + //nolint:contextcheck go func() { // The context will be derived from the channel context. err := virtual.watchVirtual() diff --git a/client/virtual_channel_settlement.go b/client/virtual_channel_settlement.go index 28982e0cf..02254a122 100644 --- a/client/virtual_channel_settlement.go +++ b/client/virtual_channel_settlement.go @@ -16,6 +16,7 @@ package client import ( "context" + "math" "github.com/pkg/errors" @@ -40,16 +41,16 @@ func (c *Channel) withdrawVirtualChannel(ctx context.Context, virtual *Channel) c.Log().Panicf("sub-allocation %x not found", virtualAlloc.ID) } - if !virtualAlloc.BalancesEqual(virtual.state().Allocation.Sum()) { + if !virtualAlloc.BalancesEqual(virtual.state().Sum()) { c.Log().Panic("sub-allocation does not equal accumulated sub-channel outcome") } virtualBalsRemapped := virtual.translateBalances(virtualAlloc.IndexMap) // We assume that the asset types of parent channel and virtual channel are the same. - state.Allocation.Balances = state.Allocation.Balances.Add(virtualBalsRemapped) + state.Balances = state.Add(virtualBalsRemapped) - if err := state.Allocation.RemoveSubAlloc(virtualAlloc); err != nil { + if err := state.RemoveSubAlloc(virtualAlloc); err != nil { c.Log().WithError(err).Panicf("removing sub-allocation with id %x", virtualAlloc.ID) } @@ -214,6 +215,9 @@ func (c *Channel) forceFinalState(ctx context.Context, final channel.SignedState return err } for i, sig := range final.Sigs { + if i < 0 || i > math.MaxUint16 { + return errors.Errorf("index out of bounds: %d", i) + } if err := c.machine.AddSig(ctx, channel.Index(i), sig); err != nil { return err } diff --git a/client/virtual_channel_test.go b/client/virtual_channel_test.go index b8e746d50..7d80156ec 100644 --- a/client/virtual_channel_test.go +++ b/client/virtual_channel_test.go @@ -67,6 +67,7 @@ func makeVirtualChannelSetup(rng *rand.Rand) ctest.VirtualChannelSetup { BalanceDelta: big.NewInt(0), Rng: rng, WaitWatcherTimeout: 100 * time.Millisecond, + IsUTXO: true, } } diff --git a/log/levellified.go b/log/levellified.go index 1fa57e1ee..2364fb69e 100644 --- a/log/levellified.go +++ b/log/levellified.go @@ -69,14 +69,14 @@ func (l *Levellified) Tracef(format string, args ...interface{}) { // Trace implements log level trace. func (l *Levellified) Trace(args ...interface{}) { if l.Lvl >= TraceLevel { - l.StdLogger.Print(prepend("[trace] ", args)...) + l.Print(prepend("[trace] ", args)...) } } // Traceln implements log.TraceLn with white spaces in between arguments. func (l *Levellified) Traceln(args ...interface{}) { if l.Lvl >= TraceLevel { - l.StdLogger.Println(prepend("[trace]", args)...) + l.Println(prepend("[trace]", args)...) } } @@ -88,14 +88,14 @@ func (l *Levellified) Debugf(format string, args ...interface{}) { // Debug implements log level debug. func (l *Levellified) Debug(args ...interface{}) { if l.Lvl >= DebugLevel { - l.StdLogger.Print(prepend("[debug] ", args)...) + l.Print(prepend("[debug] ", args)...) } } // Debugln implements log.Debugln with white spaces in between arguments. func (l *Levellified) Debugln(args ...interface{}) { if l.Lvl >= DebugLevel { - l.StdLogger.Println(prepend("[debug]", args)...) + l.Println(prepend("[debug]", args)...) } } @@ -107,14 +107,14 @@ func (l *Levellified) Infof(format string, args ...interface{}) { // Info implements log level info. func (l *Levellified) Info(args ...interface{}) { if l.Lvl >= InfoLevel { - l.StdLogger.Print(prepend("[info] ", args)...) + l.Print(prepend("[info] ", args)...) } } // Infoln implements log.Infoln with white spaces in between arguments. func (l *Levellified) Infoln(args ...interface{}) { if l.Lvl >= InfoLevel { - l.StdLogger.Println(prepend("[info]", args)...) + l.Println(prepend("[info]", args)...) } } @@ -126,14 +126,14 @@ func (l *Levellified) Warnf(format string, args ...interface{}) { // Warn implements log level warn. func (l *Levellified) Warn(args ...interface{}) { if l.Lvl >= WarnLevel { - l.StdLogger.Print(prepend("[warn] ", args)...) + l.Print(prepend("[warn] ", args)...) } } // Warnln implements log.Warnln with white spaces in between arguments. func (l *Levellified) Warnln(args ...interface{}) { if l.Lvl >= WarnLevel { - l.StdLogger.Println(prepend("[warn]", args)...) + l.Println(prepend("[warn]", args)...) } } @@ -145,20 +145,20 @@ func (l *Levellified) Errorf(format string, args ...interface{}) { // Error implements log level error. func (l *Levellified) Error(args ...interface{}) { if l.Lvl >= ErrorLevel { - l.StdLogger.Print(prepend("[error] ", args)...) + l.Print(prepend("[error] ", args)...) } } // Errorln implements log.Errorln with white spaces in between arguments. func (l *Levellified) Errorln(args ...interface{}) { if l.Lvl >= ErrorLevel { - l.StdLogger.Println(prepend("[error]", args)...) + l.Println(prepend("[error]", args)...) } } func (l *Levellified) lprintf(lvl Level, format string, args ...interface{}) { if l.Lvl >= lvl { - l.StdLogger.Printf("[%v] "+format, prepend(lvl, args)...) + l.Printf("[%v] "+format, prepend(lvl, args)...) } } diff --git a/log/log.go b/log/log.go index c84497659..c58c75631 100644 --- a/log/log.go +++ b/log/log.go @@ -72,6 +72,8 @@ type StdLogger interface { } // LevelLogger is an extension to the StdLogger with different verbosity levels. +// +//nolint:interfacebloat type LevelLogger interface { StdLogger // Tracef logs a message at level Trace. Arguments are handled in the manner of fmt.Printf. diff --git a/log/logrus/logrus_internal_test.go b/log/logrus/logrus_internal_test.go index 874f313d3..6f5b4bebe 100644 --- a/log/logrus/logrus_internal_test.go +++ b/log/logrus/logrus_internal_test.go @@ -45,9 +45,9 @@ func testLogrusInfo(t *testing.T) { logger, hook := test.NewNullLogger() FromLogrus(logger).Println("Anton Ausdemhaus") - assert.Equal(t, len(hook.Entries), 1) - assert.Equal(t, hook.LastEntry().Level, logrus.InfoLevel) - assert.Equal(t, hook.LastEntry().Message, "Anton Ausdemhaus") + assert.Len(t, hook.Entries, 1) + assert.Equal(t, logrus.InfoLevel, hook.LastEntry().Level) + assert.Equal(t, "Anton Ausdemhaus", hook.LastEntry().Message) } func testLogrusStringer(t *testing.T) { @@ -83,7 +83,7 @@ func testLogrusWithField(t *testing.T) { logger.SetLevel(logrus.DebugLevel) FromLogrus(logger).WithField("field", 123456).Debugln("Bertha Bremsweg") - assert.Equal(t, len(hook.Entries), 1) + assert.Len(t, hook.Entries, 1) assert.Equal(t, hook.LastEntry().Level, logrus.DebugLevel) assert.Equal(t, hook.LastEntry().Message, "Bertha Bremsweg") assert.Contains(t, hook.LastEntry().Data, "field") diff --git a/wallet/address.go b/wallet/address.go index 429983b36..047db6887 100644 --- a/wallet/address.go +++ b/wallet/address.go @@ -19,6 +19,7 @@ import ( "encoding" "fmt" stdio "io" + "math" "strings" "github.com/pkg/errors" @@ -134,12 +135,20 @@ type AddrKey string // Encode encodes first the length of the map, // then all Addresses and their key in the map. func (a AddressDecMap) Encode(w stdio.Writer) error { - length := int32(len(a)) + l := len(a) + if l < math.MinInt32 || l > math.MaxInt32 { + return errors.New("map length out of bounds") + } + length := int32(l) if err := perunio.Encode(w, length); err != nil { return errors.WithMessage(err, "encoding map length") } for i, addr := range a { - if err := perunio.Encode(w, int32(i)); err != nil { + id := int(i) + if id < math.MinInt32 || id > math.MaxInt32 { + return errors.New("map index out of bounds") + } + if err := perunio.Encode(w, int32(id)); err != nil { return errors.WithMessage(err, "encoding map index") } if err := perunio.Encode(w, addr); err != nil { @@ -152,7 +161,11 @@ func (a AddressDecMap) Encode(w stdio.Writer) error { // Encode encodes first the length of the array, // then all AddressDecMaps in the array. func (a AddressMapArray) Encode(w stdio.Writer) error { - length := int32(len(a.Addr)) + l := len(a.Addr) + if l > math.MaxInt32 { + return errors.New("array length out of bounds") + } + length := int32(l) if err := perunio.Encode(w, length); err != nil { return errors.WithMessage(err, "encoding array length") } @@ -172,7 +185,7 @@ func (a *AddressDecMap) Decode(r stdio.Reader) (err error) { return errors.WithMessage(err, "decoding map length") } *a = make(map[BackendID]Address, mapLen) - for i := 0; i < int(mapLen); i++ { + for i := range mapLen { var idx int32 if err := perunio.Decode(r, &idx); err != nil { return errors.WithMessage(err, "decoding map index") @@ -193,7 +206,7 @@ func (a *AddressMapArray) Decode(r stdio.Reader) (err error) { return errors.WithMessage(err, "decoding array length") } a.Addr = make([]map[BackendID]Address, mapLen) - for i := 0; i < int(mapLen); i++ { + for i := range mapLen { if err := perunio.Decode(r, (*AddressDecMap)(&a.Addr[i])); err != nil { return errors.WithMessagef(err, "decoding %d-th address map entry", i) } @@ -206,7 +219,11 @@ func (a *AddressMapArray) Decode(r stdio.Reader) (err error) { // Panics when the `Address` can't be encoded. func Key(a Address) AddrKey { var buff strings.Builder - if err := perunio.Encode(&buff, uint32(a.BackendID())); err != nil { + id := int(a.BackendID()) + if id < 0 || id > math.MaxUint32 { + panic("backend ID out of range") + } + if err := perunio.Encode(&buff, uint32(id)); err != nil { panic("Could not encode id in AddrKey: " + err.Error()) } if err := perunio.Encode(&buff, a); err != nil { diff --git a/wallet/sig.go b/wallet/sig.go index 881d2e4d1..27beb51b0 100644 --- a/wallet/sig.go +++ b/wallet/sig.go @@ -57,7 +57,7 @@ func (s SigDec) Decode(r io.Reader) (err error) { return err } -// EncodeSparseSigs encodes a collection of signatures in the form ( mask, sig, sig, sig, ...). +// EncodeSparseSigs encodes a collection of signatures in the form ( mask, sig, ...). func EncodeSparseSigs(w io.Writer, sigs []Sig) error { n := len(sigs) @@ -83,7 +83,7 @@ func EncodeSparseSigs(w io.Writer, sigs []Sig) error { return nil } -// DecodeSparseSigs decodes a collection of signatures in the form (mask, sig, sig, sig, ...). +// DecodeSparseSigs decodes a collection of signatures in the form (mask, sig, ...). func DecodeSparseSigs(r io.Reader, sigs *[]Sig) (err error) { masklen := int(math.Ceil(float64(len(*sigs)) / float64(bitsPerByte))) mask := make([]uint8, masklen) diff --git a/wallet/test/address.go b/wallet/test/address.go index bbd45ab7f..8986dc150 100644 --- a/wallet/test/address.go +++ b/wallet/test/address.go @@ -29,7 +29,7 @@ import ( func TestAddress(t *testing.T, s *Setup) { //nolint:revive // `test.Test...` stutters, but we accept that here. null := s.ZeroAddress addr := s.Backend.NewAddress() - assert.NoError(t, addr.UnmarshalBinary(s.AddressMarshalled), "Byte deserialization of address should work") + require.NoError(t, addr.UnmarshalBinary(s.AddressMarshalled), "Byte deserialization of address should work") // Test Address.String. nullString := null.String() @@ -44,9 +44,9 @@ func TestAddress(t *testing.T, s *Setup) { //nolint:revive // `test.Test...` stu // Test Address.Bytes. addrBytes, err := addr.MarshalBinary() - assert.NoError(t, err, "Marshaling address should not error") + require.NoError(t, err, "Marshaling address should not error") nullBytes, err := null.MarshalBinary() - assert.NoError(t, err, "Marshaling zero address should not error") + require.NoError(t, err, "Marshaling zero address should not error") assert.False(t, bytes.Equal(addrBytes, nullBytes), "Expected inequality of byte representations of nonzero and zero address") // a.Equal(Decode(Encode(a))) diff --git a/wallet/test/wallet.go b/wallet/test/wallet.go index a520388f9..663d8059f 100644 --- a/wallet/test/wallet.go +++ b/wallet/test/wallet.go @@ -45,20 +45,20 @@ type Setup struct { // This function should be called by every implementation of the wallet interface. func TestAccountWithWalletAndBackend(t *testing.T, s *Setup) { //nolint:revive // `test.Test...` stutters, but we accept that here. acc, err := s.Wallet.Unlock(s.AddressInWallet) - assert.NoError(t, err) + require.NoError(t, err) // Check unlocked account sig, err := acc.SignData(s.DataToSign) - assert.NoError(t, err, "Sign with unlocked account should succeed") + require.NoError(t, err, "Sign with unlocked account should succeed") valid, err := s.Backend.VerifySignature(s.DataToSign, sig, s.AddressInWallet) assert.True(t, valid, "Verification should succeed") - assert.NoError(t, err, "Verification should not produce error") + require.NoError(t, err, "Verification should not produce error") addr := s.Backend.NewAddress() err = addr.UnmarshalBinary(s.AddressMarshalled) - assert.NoError(t, err, "Binary unmarshalling of address should work") + require.NoError(t, err, "Binary unmarshalling of address should work") valid, err = s.Backend.VerifySignature(s.DataToSign, sig, addr) assert.False(t, valid, "Verification with wrong address should fail") - assert.NoError(t, err, "Verification of valid signature should not produce error") + require.NoError(t, err, "Verification of valid signature should not produce error") tampered := make([]byte, len(sig)) copy(tampered, sig) @@ -90,7 +90,7 @@ func TestAccountWithWalletAndBackend(t *testing.T, s *Setup) { //nolint:revive / err = perunio.Encode(buff, sig) require.NoError(t, err, "encode sig") sign2, err := s.Backend.DecodeSig(buff) - assert.NoError(t, err, "Decoded signature should work") + require.NoError(t, err, "Decoded signature should work") assert.Equal(t, sig, sign2, "Decoded signature should be equal to the original") // Test DecodeSig on short stream @@ -113,13 +113,13 @@ func GenericSignatureSizeTest(t *testing.T, s *Setup) { // Test that signatures have constant length l := len(sign) - for i := 0; i < 8; i++ { + for range 8 { t.Run("parallel signing", func(t *testing.T) { t.Parallel() - for i := 0; i < 256; i++ { + for range 256 { sign, err := acc.SignData(s.DataToSign) require.NoError(t, err, "Sign with unlocked account should succeed") - require.Equal(t, l, len(sign), "Signatures should have constant length: %d vs %d", l, len(sign)) + require.Len(t, sign, l, "Signatures should have constant length: %d vs %d", l, len(sign)) } }) } diff --git a/wallet/test/walletbench.go b/wallet/test/walletbench.go index b5cc5709f..563a1ffa9 100644 --- a/wallet/test/walletbench.go +++ b/wallet/test/walletbench.go @@ -32,7 +32,7 @@ func benchAccountSign(b *testing.B, s *Setup) { perunAcc, err := s.Wallet.Unlock(s.AddressInWallet) require.NoError(b, err) - for n := 0; n < b.N; n++ { + for range b.N { _, err := perunAcc.SignData(s.DataToSign) if err != nil { b.Fatal(err) @@ -61,7 +61,7 @@ func benchBackendVerifySig(b *testing.B, s *Setup) { require.NoError(b, err) b.StartTimer() - for n := 0; n < b.N; n++ { + for range b.N { ok, err := s.Backend.VerifySignature(s.DataToSign, signature, perunAcc.Address()) if !ok { @@ -72,7 +72,7 @@ func benchBackendVerifySig(b *testing.B, s *Setup) { func benchUnmarshalAddress(b *testing.B, s *Setup) { b.Helper() - for n := 0; n < b.N; n++ { + for range b.N { addr := s.Backend.NewAddress() err := addr.UnmarshalBinary(s.AddressMarshalled) if err != nil { diff --git a/watcher/local/adjudicatorpubsub.go b/watcher/local/adjudicatorpubsub.go index 3a7fca63d..84fdaf393 100644 --- a/watcher/local/adjudicatorpubsub.go +++ b/watcher/local/adjudicatorpubsub.go @@ -45,6 +45,22 @@ func newAdjudicatorEventsPubSub() *adjudicatorPubSub { } } +// EventStream returns a channel for consuming the published adjudicator +// events. It always returns the same channel and does not support +// multiplexing. +// +// The channel will be closed when the pub-sub instance is closed and Err +// should tell the possible error. +func (a *adjudicatorPubSub) EventStream() <-chan channel.AdjudicatorEvent { + return a.pipe +} + +// Err always returns nil. Because, there will be no errors when closing a +// local subscription. +func (a *adjudicatorPubSub) Err() error { + return nil +} + // publish publishes the given adjudicator event to the subscriber. // // Panics if the pub-sub instance is already closed. It is implemented this @@ -65,19 +81,3 @@ func (a *adjudicatorPubSub) publish(e channel.AdjudicatorEvent) { func (a *adjudicatorPubSub) close() { a.once.Do(func() { close(a.pipe) }) } - -// EventStream returns a channel for consuming the published adjudicator -// events. It always returns the same channel and does not support -// multiplexing. -// -// The channel will be closed when the pub-sub instance is closed and Err -// should tell the possible error. -func (a *adjudicatorPubSub) EventStream() <-chan channel.AdjudicatorEvent { - return a.pipe -} - -// Err always returns nil. Because, there will be no errors when closing a -// local subscription. -func (a *adjudicatorPubSub) Err() error { - return nil -} diff --git a/watcher/local/watcher.go b/watcher/local/watcher.go index 45e466c01..53d1c3a08 100644 --- a/watcher/local/watcher.go +++ b/watcher/local/watcher.go @@ -160,7 +160,7 @@ func (w *Watcher) StartWatchingSubChannel( parent channel.ID, signedState channel.SignedState, ) (watcher.StatesPub, watcher.AdjudicatorSub, error) { - parentCh, ok := w.registry.retrieve(parent) + parentCh, ok := w.retrieve(parent) if !ok { return nil, nil, errors.New("parent channel not registered with the watcher") } @@ -177,6 +177,53 @@ func (w *Watcher) StartWatchingSubChannel( return statesPub, eventsSub, nil } +// StopWatching stops watching for adjudicator events, closes the pub-sub +// instances and removes the channel from the registry. +// +// The client should invoke stop watching for all the sub-channels before +// invoking for the parent ledger channel. +// +// In case of stop watching for sub-channels, watcher ensures that, when it +// receives a registered event for its parent channel or any other sub-channels +// of the parent channel, it is able to successfully refute with the latest +// states for the ledger channel and all its sub-channels (even if the watcher +// has stopped watching for some of the sub-channel). +// +// Context is not used, it is for implementing watcher.Watcher interface. +func (w *Watcher) StopWatching(_ context.Context, id channel.ID) error { + ch, ok := w.retrieve(id) + if !ok { + return errors.New("channel not registered with the watcher") + } + + parent := ch + if ch.isSubChannel() { + parent = ch.parent + } + parent.subChsAccess.Lock() + defer parent.subChsAccess.Unlock() + if ch.isClosed { + // Channel could have been closed while were waiting for the mutex locked. + return errors.New("channel not registered with the watcher") + } + close(ch.done) + + if ch.isSubChannel() { + latestParentTx := ch.parent.txRetriever.retrieve() + if _, ok := latestParentTx.SubAlloc(id); ok { + parent.archivedSubChStates[id] = makeSignedState(ch.params, ch.txRetriever.retrieve()) + } + delete(parent.subChs, id) + } else if len(ch.subChs) > 0 { + return errors.WithMessagef(ErrSubChannelsPresent, "cannot de-register: %d %v", len(ch.subChs), ch.id) + } + + closePubSubs(ch) + w.remove(ch.id) + ch.isClosed = true + return nil +} + func (w *Watcher) startWatching( ctx context.Context, parent *ch, @@ -197,7 +244,7 @@ func (w *Watcher) startWatching( return newCh(id, parent, signedState.Params, eventsFromChainSub, eventsToClientPubSub, statesPubSub, multiLedger), nil } - ch, err := w.registry.addIfSucceeds(id, chInitializer1) + ch, err := w.addIfSucceeds(id, chInitializer1) if err != nil { return nil, nil, err } @@ -206,7 +253,7 @@ func (w *Watcher) startWatching( Sigs: signedState.Sigs, } ch.Go(func() { ch.handleStatesFromClient(initialTx) }) - ch.Go(func() { ch.handleEventsFromChain(w.rs, w.registry) }) + ch.Go(func() { ch.handleEventsFromChain(w.rs, w.registry) }) //nolint:contextcheck return statesPubSub, eventsToClientPubSub, nil } @@ -415,15 +462,15 @@ func registerDispute(ctx context.Context, r *registry, registerer channel.Regist func retrieveLatestSubStates(r *registry, parent *ch) (channel.Transaction, []channel.SignedState) { parentTx := parent.txRetriever.retrieve() - subStates := make([]channel.SignedState, len(parentTx.Allocation.Locked)) - for i := range parentTx.Allocation.Locked { + subStates := make([]channel.SignedState, len(parentTx.Locked)) + for i := range parentTx.Locked { // Can be done concurrently. - subCh, ok := r.retrieve(parentTx.Allocation.Locked[i].ID) + subCh, ok := r.retrieve(parentTx.Locked[i].ID) if ok { subChTx := subCh.txRetriever.retrieve() subStates[i] = makeSignedState(subCh.params, subChTx) } else { - subStates[i] = parent.archivedSubChStates[parentTx.Allocation.Locked[i].ID] + subStates[i] = parent.archivedSubChStates[parentTx.Locked[i].ID] } } return parentTx, subStates @@ -445,53 +492,6 @@ func makeAdjudicatorReq(params *channel.Params, tx channel.Transaction) channel. } } -// StopWatching stops watching for adjudicator events, closes the pub-sub -// instances and removes the channel from the registry. -// -// The client should invoke stop watching for all the sub-channels before -// invoking for the parent ledger channel. -// -// In case of stop watching for sub-channels, watcher ensures that, when it -// receives a registered event for its parent channel or any other sub-channels -// of the parent channel, it is able to successfully refute with the latest -// states for the ledger channel and all its sub-channels (even if the watcher -// has stopped watching for some of the sub-channel). -// -// Context is not used, it is for implementing watcher.Watcher interface. -func (w *Watcher) StopWatching(_ context.Context, id channel.ID) error { - ch, ok := w.retrieve(id) - if !ok { - return errors.New("channel not registered with the watcher") - } - - parent := ch - if ch.isSubChannel() { - parent = ch.parent - } - parent.subChsAccess.Lock() - defer parent.subChsAccess.Unlock() - if ch.isClosed { - // Channel could have been closed while were waiting for the mutex locked. - return errors.New("channel not registered with the watcher") - } - close(ch.done) - - if ch.isSubChannel() { - latestParentTx := ch.parent.txRetriever.retrieve() - if _, ok := latestParentTx.SubAlloc(id); ok { - parent.archivedSubChStates[id] = makeSignedState(ch.params, ch.txRetriever.retrieve()) - } - delete(parent.subChs, id) - } else if len(ch.subChs) > 0 { - return errors.WithMessagef(ErrSubChannelsPresent, "cannot de-register: %d %v", len(ch.subChs), ch.id) - } - - closePubSubs(ch) - w.remove(ch.id) - ch.isClosed = true - return nil -} - func closePubSubs(ch *ch) { if err := ch.eventsFromChainSub.Close(); err != nil { err := errors.WithMessage(err, "closing events from chain sub") diff --git a/watcher/local/watcher_test.go b/watcher/local/watcher_test.go index 5e026b684..abeec70b4 100644 --- a/watcher/local/watcher_test.go +++ b/watcher/local/watcher_test.go @@ -242,7 +242,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 3) // Add sub-channel to allocation. This transaction represents funding of the sub-channel. - parentTxs[2].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} + parentTxs[2].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent, makeRegisteredEvents(parentTxs[2])...) @@ -262,7 +262,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { // Child: Publish both the states to the watcher. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - statesPubChild, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + statesPubChild, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) require.NoError(t, statesPubChild.Publish(context.Background(), childTxs[1])) require.NoError(t, statesPubChild.Publish(context.Background(), childTxs[2])) @@ -281,7 +281,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 3) // Add sub-channel to allocation. This transaction represents funding of the sub-channel. - parentTxs[2].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} + parentTxs[2].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent, makeRegisteredEvents(parentTxs[2])...) @@ -301,7 +301,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { // Child: Publish only one of the two newly created off-chain states to the watcher. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - statesPubChild, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + statesPubChild, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) require.NoError(t, statesPubChild.Publish(context.Background(), childTxs[1])) // Parent, Child: Trigger adjudicator events with a state newer than @@ -325,7 +325,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 3) // Add sub-channel to allocation. This transaction represents funding of the sub-channel. - parentTxs[2].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} + parentTxs[2].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent, makeRegisteredEvents(parentTxs[1], parentTxs[2])...) @@ -347,7 +347,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { // Child: Publish both the states to the watcher. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - childStatesPub, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + childStatesPub, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) require.NoError(t, childStatesPub.Publish(context.Background(), childTxs[1])) require.NoError(t, childStatesPub.Publish(context.Background(), childTxs[2])) @@ -384,7 +384,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 4) // Add sub-channel to allocation. This transaction represents funding of the sub-channel. - parentTxs[2].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} + parentTxs[2].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent, makeRegisteredEvents(parentTxs[1], parentTxs[2])...) @@ -408,7 +408,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { // Child: Publish both the states to the watcher. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - childStatesPub, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + childStatesPub, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) require.NoError(t, childStatesPub.Publish(context.Background(), childTxs[1])) require.NoError(t, childStatesPub.Publish(context.Background(), childTxs[2])) @@ -441,7 +441,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { // Setup: Generate the params and off-chain states for a ledger channel and a sub-channel. parentParams, parentTxs := randomTxsForSingleCh(rng, 2) childParams, childTxs := randomTxsForSingleCh(rng, 2) - parentTxs[1].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // Add sub-channel to allocation. + parentTxs[1].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // Add sub-channel to allocation. // Setup: Adjudicator event subscription for the ledger and sub-channel. adjSubParent := &mocks.AdjudicatorSubscription{} @@ -457,7 +457,7 @@ func Test_Watcher_WithSubchannel(t *testing.T) { parentSignedState := makeSignedStateWDummySigs(parentParams, parentTxs[0].State) _, eventsForClientParent := startWatchingForLedgerChannel(t, w, parentSignedState) childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - _, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + _, eventsForClientChild := startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) // Trigger the events for both (the ledger channel and the sub-channel) and, assert if they are relayed to // the adjudicator subscription (eventsForClient). @@ -495,7 +495,7 @@ func Test_Watcher_StopWatching(t *testing.T) { w := newWatcher(t, rs) startWatchingForLedgerChannel(t, w, makeSignedStateWDummySigs(params, txs[0].State)) - require.NoError(t, w.StopWatching(context.Background(), txs[0].State.ID)) + require.NoError(t, w.StopWatching(context.Background(), txs[0].ID)) rs.AssertExpectations(t) } @@ -517,10 +517,10 @@ func Test_Watcher_StopWatching(t *testing.T) { startWatchingForLedgerChannel(t, w, makeSignedStateWDummySigs(params, txs[0].State)) wg := sync.WaitGroup{} - for i := 0; i < 2; i++ { + for range 2 { wg.Add(1) go func() { - w.StopWatching(context.Background(), txs[0].State.ID) //nolint:errcheck + w.StopWatching(context.Background(), txs[0].ID) //nolint:errcheck wg.Done() }() } @@ -534,8 +534,8 @@ func Test_Watcher_StopWatching(t *testing.T) { defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 1) - parentTxs[1].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. - parentTxs[2].Allocation.Locked = []channel.SubAlloc{} // sub-channel withdrawal. + parentTxs[1].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. + parentTxs[2].Locked = []channel.SubAlloc{} // sub-channel withdrawal. adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent) @@ -556,12 +556,12 @@ func Test_Watcher_StopWatching(t *testing.T) { // Child: Start watching. Parent: Publish sub-channel withdrawal transaction childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) require.NoError(t, statesPub.Publish(context.Background(), parentTxs[2])) // Child, then Parent: Stop Watching. - require.NoError(t, w.StopWatching(context.Background(), childTxs[0].State.ID)) - require.NoError(t, w.StopWatching(context.Background(), parentTxs[0].State.ID)) + require.NoError(t, w.StopWatching(context.Background(), childTxs[0].ID)) + require.NoError(t, w.StopWatching(context.Background(), parentTxs[0].ID)) rs.AssertExpectations(t) }) @@ -570,7 +570,7 @@ func Test_Watcher_StopWatching(t *testing.T) { defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 3) - parentTxs[2].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. + parentTxs[2].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent, makeRegisteredEvents(parentTxs[2])[0]) @@ -592,14 +592,14 @@ func Test_Watcher_StopWatching(t *testing.T) { // Child: Start watching. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) // Child: Stop watching. - require.NoError(t, w.StopWatching(context.Background(), childTxs[0].State.ID)) + require.NoError(t, w.StopWatching(context.Background(), childTxs[0].ID)) // Parent: Trigger event with latest state and expect refutation with parent, child transactions. triggerAdjEventAndExpectNotification(t, triggerParent, eventsForClientParent) // Parent: Stop watching. - require.NoError(t, w.StopWatching(context.Background(), parentTxs[0].State.ID)) + require.NoError(t, w.StopWatching(context.Background(), parentTxs[0].ID)) rs.AssertExpectations(t) }) @@ -608,7 +608,7 @@ func Test_Watcher_StopWatching(t *testing.T) { defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 3) - parentTxs[2].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. + parentTxs[2].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent, makeRegisteredEvents(parentTxs[1])[0]) @@ -631,14 +631,14 @@ func Test_Watcher_StopWatching(t *testing.T) { // Child: Start watching. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) // Child: Stop watching. - require.NoError(t, w.StopWatching(context.Background(), childTxs[0].State.ID)) + require.NoError(t, w.StopWatching(context.Background(), childTxs[0].ID)) // Parent: Trigger event with latest state and expect refutation with parent, child transactions. triggerAdjEventAndExpectNotification(t, triggerParent, eventsForClientParent) // Parent: Stop watching. - require.NoError(t, w.StopWatching(context.Background(), parentTxs[0].State.ID)) + require.NoError(t, w.StopWatching(context.Background(), parentTxs[0].ID)) rs.AssertExpectations(t) }) @@ -646,7 +646,7 @@ func Test_Watcher_StopWatching(t *testing.T) { t.Run("error/stopParent_woSettleOnParent_woStopChild", func(t *testing.T) { parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 3) - parentTxs[2].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. + parentTxs[2].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent) @@ -668,10 +668,10 @@ func Test_Watcher_StopWatching(t *testing.T) { // Child: Start watching. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) // Parent: Stop watching (error). - require.Error(t, w.StopWatching(context.Background(), parentTxs[0].State.ID)) + require.Error(t, w.StopWatching(context.Background(), parentTxs[0].ID)) rs.AssertExpectations(t) }) @@ -679,8 +679,8 @@ func Test_Watcher_StopWatching(t *testing.T) { t.Run("error/stopParent_SettleOnParent_woStopChild", func(t *testing.T) { parentParams, parentTxs := randomTxsForSingleCh(rng, 3) childParams, childTxs := randomTxsForSingleCh(rng, 3) - parentTxs[1].Allocation.Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. - parentTxs[2].Allocation.Locked = []channel.SubAlloc{} // sub-channel withdrawal. + parentTxs[1].Locked = []channel.SubAlloc{{ID: childTxs[0].ID}} // sub-channel funding. + parentTxs[2].Locked = []channel.SubAlloc{} // sub-channel withdrawal. adjSubParent := &mocks.AdjudicatorSubscription{} triggerParent := setExpectationNextCall(adjSubParent) @@ -702,10 +702,10 @@ func Test_Watcher_StopWatching(t *testing.T) { // Child: Start watching. childSignedState := makeSignedStateWDummySigs(childParams, childTxs[0].State) - startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].State.ID) + startWatchingForSubChannel(t, w, childSignedState, parentTxs[0].ID) // Parent: Stop watching (error). - require.Error(t, w.StopWatching(context.Background(), parentTxs[0].State.ID)) + require.Error(t, w.StopWatching(context.Background(), parentTxs[0].ID)) rs.AssertExpectations(t) }) @@ -733,7 +733,10 @@ func randomTxsForSingleCh(rng *rand.Rand, n int) (*channel.Params, []channel.Tra txs := make([]channel.Transaction, n) for i := range txs { txs[i] = channel.Transaction{State: initialState.Clone()} - txs[i].State.Version = uint64(i) + if i < 0 { + panic("i < 0") + } + txs[i].Version = uint64(i) } return params, txs } @@ -774,6 +777,8 @@ func (t *adjEventSource) close() { // the "Subscribe" method to be called once. The adjSub and the err are set as // the return values for the call and will be returned when the method is // called. +// +//nolint:unparam func setExpectationSubscribeCall(rs *mocks.RegisterSubscriber, adjSub channel.AdjudicatorSubscription, err error) { rs.On("Subscribe", testifyMock.Anything, testifyMock.Anything).Return(adjSub, err).Once() } @@ -865,7 +870,7 @@ func setExpectationRegisterCalls(t *testing.T, rs *mocks.RegisterSubscriber, cha func assertEqualAdjudicatorReq(t *testing.T, got channel.AdjudicatorReq, want *channel.State) bool { t.Helper() - if nil != got.Tx.State.Equal(want) { + if nil != got.Tx.Equal(want) { t.Logf("Got %+v, expected %+v", got.Tx.State, want) return false } @@ -894,9 +899,9 @@ func makeRegisteredEvents(txs ...channel.Transaction) []channel.AdjudicatorEvent State: tx.State, Sigs: tx.Sigs, AdjudicatorEventBase: channel.AdjudicatorEventBase{ - IDV: tx.State.ID, + IDV: tx.ID, TimeoutV: &channel.ElapsedTimeout{}, - VersionV: tx.State.Version, + VersionV: tx.Version, }, } } @@ -910,9 +915,9 @@ func makeProgressedEvents(txs ...channel.Transaction) []channel.AdjudicatorEvent State: tx.State, Idx: channel.Index(0), AdjudicatorEventBase: channel.AdjudicatorEventBase{ - IDV: tx.State.ID, + IDV: tx.ID, TimeoutV: &channel.ElapsedTimeout{}, - VersionV: tx.State.Version, + VersionV: tx.Version, }, } } @@ -924,9 +929,9 @@ func makeConcludedEvents(txs ...channel.Transaction) []channel.AdjudicatorEvent for i, tx := range txs { events[i] = &channel.ConcludedEvent{ AdjudicatorEventBase: channel.AdjudicatorEventBase{ - IDV: tx.State.ID, + IDV: tx.ID, TimeoutV: &channel.ElapsedTimeout{}, - VersionV: tx.State.Version, + VersionV: tx.Version, }, } } diff --git a/wire/account.go b/wire/account.go index dd1bbeab0..1d5391b8f 100644 --- a/wire/account.go +++ b/wire/account.go @@ -18,6 +18,7 @@ import ( "encoding/binary" "fmt" "io" + "math" "perun.network/go-perun/wallet" ) @@ -56,7 +57,11 @@ func (m *AuthResponseMsg) Type() Type { // It writes the signature to the writer. func (m *AuthResponseMsg) Encode(w io.Writer) error { // Write the length of the signature - err := binary.Write(w, binary.BigEndian, uint32(len(m.Signature))) + l := len(m.Signature) + if l > math.MaxUint32 { + return fmt.Errorf("signature length out of bounds: %d", len(m.Signature)) + } + err := binary.Write(w, binary.BigEndian, uint32(l)) if err != nil { return fmt.Errorf("failed to write signature length: %w", err) } diff --git a/wire/address.go b/wire/address.go index 39492fc52..5d58bc1b4 100644 --- a/wire/address.go +++ b/wire/address.go @@ -17,6 +17,7 @@ package wire import ( "encoding" stdio "io" + "math" "sort" "strings" @@ -58,12 +59,20 @@ type AddressDecMap map[wallet.BackendID]Address // Encode encodes first the length of the map, // then all Addresses and their key in the map. func (a AddressDecMap) Encode(w stdio.Writer) error { - length := int32(len(a)) + l := len(a) + if l > math.MaxInt32 { + return errors.New("map length out of bounds") + } + length := int32(l) if err := perunio.Encode(w, length); err != nil { return errors.WithMessage(err, "encoding map length") } for i, addr := range a { - if err := perunio.Encode(w, int32(i)); err != nil { + id := int(i) + if id < math.MinInt32 || id > math.MaxInt32 { + return errors.New("map index out of bounds") + } + if err := perunio.Encode(w, int32(id)); err != nil { return errors.WithMessage(err, "encoding map index") } if err := perunio.Encode(w, addr); err != nil { @@ -76,7 +85,11 @@ func (a AddressDecMap) Encode(w stdio.Writer) error { // Encode encodes first the length of the array, // then all AddressDecMaps in the array. func (a AddressMapArray) Encode(w stdio.Writer) error { - length := int32(len(a)) + l := len(a) + if l < math.MinInt32 || l > math.MaxInt32 { + return errors.New("array length out of bounds") + } + length := int32(l) if err := perunio.Encode(w, length); err != nil { return errors.WithMessage(err, "encoding array length") } @@ -95,7 +108,7 @@ func (a *AddressDecMap) Decode(r stdio.Reader) (err error) { return errors.WithMessage(err, "decoding map length") } *a = make(map[wallet.BackendID]Address, mapLen) - for i := 0; i < int(mapLen); i++ { + for i := range mapLen { var idx int32 if err := perunio.Decode(r, &idx); err != nil { return errors.WithMessage(err, "decoding map index") @@ -117,7 +130,7 @@ func (a *AddressMapArray) Decode(r stdio.Reader) (err error) { return errors.WithMessage(err, "decoding array length") } *a = make([]map[wallet.BackendID]Address, mapLen) - for i := 0; i < int(mapLen); i++ { + for i := range mapLen { if err := perunio.Decode(r, (*AddressDecMap)(&(*a)[i])); err != nil { return errors.WithMessagef(err, "decoding %d-th address map entry", i) } diff --git a/wire/cache_internal_test.go b/wire/cache_internal_test.go index 4de3acff7..10cb3c3d5 100644 --- a/wire/cache_internal_test.go +++ b/wire/cache_internal_test.go @@ -61,7 +61,7 @@ func TestCache(t *testing.T) { c.Release(&isPing) assert.False(c.Put(ping2), "Put into cache with canceled predicate") assert.Equal(2, c.Size()) - assert.Len(c.preds, 0, "internal: Put should have removed canceled predicate") + assert.Empty(c.preds, "internal: Put should have removed canceled predicate") msgs := c.Messages(func(e *Envelope) bool { return e.Msg.Type() == Ping && diff --git a/wire/controlmsgs.go b/wire/controlmsgs.go index 9d0c955ef..6b96b9af4 100644 --- a/wire/controlmsgs.go +++ b/wire/controlmsgs.go @@ -61,16 +61,16 @@ type PingMsg struct { PingPongMsg } -// Type returns Ping. -func (m *PingMsg) Type() Type { - return Ping -} - // NewPingMsg creates a new Ping message. func NewPingMsg() *PingMsg { return &PingMsg{newPingPongMsg()} } +// Type returns Ping. +func (m *PingMsg) Type() Type { + return Ping +} + // PongMsg is the response to a ping message. // It contains the time at which it was sent, so that the recipient knows how // long the ping request took to be transmitted, and how quickly the response @@ -79,16 +79,16 @@ type PongMsg struct { PingPongMsg } -// Type returns Pong. -func (m *PongMsg) Type() Type { - return Pong -} - // NewPongMsg creates a new Pong message. func NewPongMsg() *PongMsg { return &PongMsg{newPingPongMsg()} } +// Type returns Pong. +func (m *PongMsg) Type() Type { + return Pong +} + // ShutdownMsg is sent when orderly shutting down a connection. // // Reason should be a UTF-8 encodable string. diff --git a/wire/encode_test.go b/wire/encode_test.go index fc586c617..efd32e60d 100644 --- a/wire/encode_test.go +++ b/wire/encode_test.go @@ -25,7 +25,7 @@ import ( "polycry.pt/poly-go/test" ) -var nilDecoder = func(io.Reader) (wire.Msg, error) { return nil, nil } +var nilDecoder = func(io.Reader) (wire.Msg, error) { return nil, nil } //nolint:nilnil func TestType_Valid_String(t *testing.T) { test.OnlyOnce(t) diff --git a/wire/hybridbus.go b/wire/hybridbus.go index 6015d56ec..49bab8803 100644 --- a/wire/hybridbus.go +++ b/wire/hybridbus.go @@ -66,7 +66,6 @@ func (b *hybridBus) Publish(ctx context.Context, e *Envelope) error { errg := errors.NewGatherer() for _, bus := range b.buses { - bus := bus errg.Go(func() error { err := bus.Publish(sending, e) // If sending was successful, abort all other send operations, and diff --git a/wire/net/bus_test.go b/wire/net/bus_test.go index de169d6bd..cd98325eb 100644 --- a/wire/net/bus_test.go +++ b/wire/net/bus_test.go @@ -17,10 +17,9 @@ package net_test import ( "testing" + "github.com/stretchr/testify/require" "perun.network/go-perun/wallet" - "github.com/stretchr/testify/assert" - "perun.network/go-perun/wire" "perun.network/go-perun/wire/net" nettest "perun.network/go-perun/wire/net/test" @@ -41,5 +40,5 @@ func TestBus(t *testing.T) { return bus, bus }, numClients, numMsgs) - assert.NoError(t, hub.Close()) + require.NoError(t, hub.Close()) } diff --git a/wire/net/endpoint.go b/wire/net/endpoint.go index 902c101ab..28bc1a225 100644 --- a/wire/net/endpoint.go +++ b/wire/net/endpoint.go @@ -42,28 +42,6 @@ type Endpoint struct { sending sync.Mutex // Blocks multiple Send calls. } -// recvLoop continuously receives messages from an Endpoint until it is closed. -// Received messages are relayed via the Endpoint's subscription system. This is -// called by the registry when the Endpoint is registered. -// -// Does not return an error when the Endpoint closing fails or when -// conn.Recv returns io.EOF, which indicates connection closing for TCP. -func (p *Endpoint) recvLoop(c wire.Consumer) error { - for { - e, err := p.conn.Recv() - if err != nil { - p.Close() // Ignore double close. - // Check for graceful TCP connection close. - if errors.Cause(err) == io.EOF { - return nil - } - return err - } - // Emit the received envelope. - c.Put(e) - } -} - // Send sends a single message to an Endpoint. // Fails if the Endpoint is closed via Close() or the transmission fails. // @@ -109,3 +87,25 @@ func newEndpoint(addr map[wallet.BackendID]wire.Address, conn Conn) *Endpoint { func (p *Endpoint) String() string { return fmt.Sprint(p.Address) } + +// recvLoop continuously receives messages from an Endpoint until it is closed. +// Received messages are relayed via the Endpoint's subscription system. This is +// called by the registry when the Endpoint is registered. +// +// Does not return an error when the Endpoint closing fails or when +// conn.Recv returns io.EOF, which indicates connection closing for TCP. +func (p *Endpoint) recvLoop(c wire.Consumer) error { + for { + e, err := p.conn.Recv() + if err != nil { + p.Close() // Ignore double close. + // Check for graceful TCP connection close. + if errors.Cause(err) == io.EOF { + return nil + } + return err + } + // Emit the received envelope. + c.Put(e) + } +} diff --git a/wire/net/endpoint_internal_test.go b/wire/net/endpoint_internal_test.go index 0abe4734f..f37ab09c9 100644 --- a/wire/net/endpoint_internal_test.go +++ b/wire/net/endpoint_internal_test.go @@ -26,6 +26,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" _ "perun.network/go-perun/backend/sim" // backend init "perun.network/go-perun/wire" @@ -120,7 +121,7 @@ func TestEndpoint_Close(t *testing.T) { found := s.alice.Registry.find(bobAddr) assert.Equal(t, s.alice.endpoint, found) // Close Alice's connection to Bob. - assert.NoError(t, s.alice.endpoint.Close(), "closing a peer once must succeed") + require.NoError(t, s.alice.endpoint.Close(), "closing a peer once must succeed") assert.Error(t, s.alice.endpoint.Close(), "closing peers twice must fail") // Sending over closed peers (not connections) must fail. diff --git a/wire/net/endpoint_registry.go b/wire/net/endpoint_registry.go index 79be8eee9..6539ca528 100644 --- a/wire/net/endpoint_registry.go +++ b/wire/net/endpoint_registry.go @@ -165,29 +165,6 @@ func (r *EndpointRegistry) Listen(listener Listener) { } } -// setupConn authenticates a fresh connection, and if successful, adds it to the -// registry. -func (r *EndpointRegistry) setupConn(conn Conn) error { - ctx, cancel := context.WithTimeout(r.Ctx(), exchangeAddrsTimeout) - defer cancel() - - var peerAddr map[wallet.BackendID]wire.Address - var err error - if peerAddr, err = ExchangeAddrsPassive(ctx, r.id, conn); err != nil { - conn.Close() - r.Log().WithField("peer", peerAddr).Error("could not authenticate peer:", err) - return err - } - - if channel.EqualWireMaps(peerAddr, wire.AddressMapfromAccountMap(r.id)) { - r.Log().Error("dialed by self") - return errors.New("dialed by self") - } - - r.addEndpoint(peerAddr, conn, false) - return nil -} - // Endpoint looks up an Endpoint via its perun address. If the Endpoint does not // exist yet, it is dialed. Does not return until the peer is dialed or the // context is closed. @@ -219,6 +196,26 @@ func (r *EndpointRegistry) Endpoint(ctx context.Context, addr map[wallet.Backend return e, errors.WithMessage(err, "failed to dial peer") } +// NumPeers returns the current number of peers in the registry including +// placeholder peers (cf. Registry.Get). +func (r *EndpointRegistry) NumPeers() int { + r.mutex.RLock() + defer r.mutex.RUnlock() + return len(r.endpoints) +} + +// Has return true if and only if there is a peer with the given address in the +// registry. The function does not differentiate between regular and +// placeholder peers. +func (r *EndpointRegistry) Has(addr map[wallet.BackendID]wire.Address) bool { + r.mutex.Lock() + defer r.mutex.Unlock() + + _, ok := r.endpoints[wire.Keys(addr)] + + return ok +} + func (r *EndpointRegistry) authenticatedDial( ctx context.Context, addr map[wallet.BackendID]wire.Address, @@ -276,26 +273,6 @@ func (r *EndpointRegistry) dialingEndpoint(a map[wallet.BackendID]wire.Address) return entry, !ok } -// NumPeers returns the current number of peers in the registry including -// placeholder peers (cf. Registry.Get). -func (r *EndpointRegistry) NumPeers() int { - r.mutex.RLock() - defer r.mutex.RUnlock() - return len(r.endpoints) -} - -// Has return true if and only if there is a peer with the given address in the -// registry. The function does not differentiate between regular and -// placeholder peers. -func (r *EndpointRegistry) Has(addr map[wallet.BackendID]wire.Address) bool { - r.mutex.Lock() - defer r.mutex.Unlock() - - _, ok := r.endpoints[wire.Keys(addr)] - - return ok -} - // addEndpoint adds a new peer to the registry. func (r *EndpointRegistry) addEndpoint(addr map[wallet.BackendID]wire.Address, conn Conn, dialer bool) *Endpoint { r.Log().WithField("peer", addr).Trace("EndpointRegistry.addEndpoint") @@ -394,3 +371,26 @@ func (r *EndpointRegistry) find(addr map[wallet.BackendID]wire.Address) *Endpoin } return nil } + +// setupConn authenticates a fresh connection, and if successful, adds it to the +// registry. +func (r *EndpointRegistry) setupConn(conn Conn) error { + ctx, cancel := context.WithTimeout(r.Ctx(), exchangeAddrsTimeout) + defer cancel() + + var peerAddr map[wallet.BackendID]wire.Address + var err error + if peerAddr, err = ExchangeAddrsPassive(ctx, r.id, conn); err != nil { + conn.Close() + r.Log().WithField("peer", peerAddr).Error("could not authenticate peer:", err) + return err + } + + if channel.EqualWireMaps(peerAddr, wire.AddressMapfromAccountMap(r.id)) { + r.Log().Error("dialed by self") + return errors.New("dialed by self") + } + + r.addEndpoint(peerAddr, conn, false) + return nil +} diff --git a/wire/net/endpoint_registry_external_test.go b/wire/net/endpoint_registry_external_test.go index 53dd657f3..4e6b5278f 100644 --- a/wire/net/endpoint_registry_external_test.go +++ b/wire/net/endpoint_registry_external_test.go @@ -60,14 +60,14 @@ func TestEndpointRegistry_Get_Pair(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 2*timeout) defer cancel() p, err := dialerReg.Endpoint(ctx, wire.AddressMapfromAccountMap(listenerID)) - assert.NoError(err) + require.NoError(err) require.NotNil(p) assert.True(channel.EqualWireMaps(p.Address, wire.AddressMapfromAccountMap(listenerID))) // should allow the listener routine to add the peer to its registry time.Sleep(timeout) p, err = listenerReg.Endpoint(ctx, wire.AddressMapfromAccountMap(dialerID)) - assert.NoError(err) + require.NoError(err) require.NotNil(p) assert.True(channel.EqualWireMaps(p.Address, wire.AddressMapfromAccountMap(dialerID))) @@ -107,7 +107,7 @@ func TestEndpointRegistry_Get_Multiple(t *testing.T) { const N = 4 peers := make(chan *net.Endpoint, N) - for i := 0; i < N; i++ { + for range N { go func() { p, err := dialerReg.Endpoint(ctx, wire.AddressMapfromAccountMap(listenerID)) assert.NoError(err) @@ -124,7 +124,7 @@ func TestEndpointRegistry_Get_Multiple(t *testing.T) { require := require.New(t) p := <-peers require.NotNil(p) - for i := 0; i < N-1; i++ { + for range N - 1 { p0 := <-peers require.NotNil(p0) assert.Same(p, p0) diff --git a/wire/net/endpoint_registry_internal_test.go b/wire/net/endpoint_registry_internal_test.go index 85173325e..f2e4c7575 100644 --- a/wire/net/endpoint_registry_internal_test.go +++ b/wire/net/endpoint_registry_internal_test.go @@ -55,7 +55,7 @@ func (d *mockDialer) Close() error { return nil } -func (d *mockDialer) Dial(ctx context.Context, addr map[wallet.BackendID]wire.Address, _ wire.EnvelopeSerializer) (Conn, error) { +func (d *mockDialer) Dial(ctx context.Context, _ map[wallet.BackendID]wire.Address, _ wire.EnvelopeSerializer) (Conn, error) { d.mutex.Lock() defer d.mutex.Unlock() @@ -132,7 +132,7 @@ func TestRegistry_Get(t *testing.T) { r.endpoints[wire.Keys(peerAddr)] = newFullEndpoint(existing) ctxtest.AssertTerminates(t, timeout, func() { p, err := r.Endpoint(context.Background(), peerAddr) - assert.NoError(t, err) + require.NoError(t, err) assert.Same(t, p, existing) }) }) @@ -166,9 +166,9 @@ func TestRegistry_Get(t *testing.T) { go ct.Stage("receiver", func(t test.ConcT) { dialer.put(a) _, err := ExchangeAddrsPassive(ctx, peerID, b) - require.NoError(t, err) + assert.NoError(t, err) _, err = b.Recv() - require.NoError(t, err) + assert.NoError(t, err) }) p, err := r.Endpoint(ctx, peerAddr) require.NoError(t, err) @@ -233,7 +233,7 @@ func TestRegistry_authenticatedDial(t *testing.T) { go ct.Stage("passive", func(rt test.ConcT) { d.put(a) _, err := ExchangeAddrsPassive(ctx, wiretest.NewRandomAccountMap(rng, channel.TestBackendID), b) - require.True(rt, IsAuthenticationError(err)) + assert.True(rt, IsAuthenticationError(err)) }) de, created := r.dialingEndpoint(remoteAddr) e, err := r.authenticatedDial(ctx, remoteAddr, de, created) @@ -257,7 +257,7 @@ func TestRegistry_authenticatedDial(t *testing.T) { defer cancel() de, created := r.dialingEndpoint(remoteAddr) e, err := r.authenticatedDial(ctx, remoteAddr, de, created) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, e) }) } @@ -300,7 +300,7 @@ func TestRegistry_setupConn(t *testing.T) { r.addEndpoint(wire.AddressMapfromAccountMap(remoteID), newMockConn(), false) ctxtest.AssertTerminates(t, timeout, func() { - assert.NoError(t, r.setupConn(a)) + require.NoError(t, r.setupConn(a)) }) }) @@ -316,7 +316,7 @@ func TestRegistry_setupConn(t *testing.T) { }() ctxtest.AssertTerminates(t, timeout, func() { - assert.NoError(t, r.setupConn(a)) + require.NoError(t, r.setupConn(a)) }) }) } diff --git a/wire/net/exchange_addr_internal_test.go b/wire/net/exchange_addr_internal_test.go index d9ddf2c3b..5d67a6a42 100644 --- a/wire/net/exchange_addr_internal_test.go +++ b/wire/net/exchange_addr_internal_test.go @@ -22,6 +22,7 @@ import ( "perun.network/go-perun/channel" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/wire" wiretest "perun.network/go-perun/wire/test" @@ -51,12 +52,12 @@ func TestExchangeAddrs_Success(t *testing.T) { defer conn1.Close() recvAddr0, err := ExchangeAddrsPassive(context.Background(), account1, conn1) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, channel.EqualWireMaps(recvAddr0, wire.AddressMapfromAccountMap(account0))) }() err := ExchangeAddrsActive(context.Background(), account0, wire.AddressMapfromAccountMap(account1), conn0) - assert.NoError(t, err) + require.NoError(t, err) wg.Wait() } diff --git a/wire/net/simple/account.go b/wire/net/simple/account.go index 799a59ab6..4973e7113 100644 --- a/wire/net/simple/account.go +++ b/wire/net/simple/account.go @@ -31,6 +31,23 @@ type Account struct { privateKey *rsa.PrivateKey } +// NewRandomAccount generates a new random account. +func NewRandomAccount(rng *rand.Rand) *Account { + keySize := 2048 + privateKey, err := rsa.GenerateKey(rng, keySize) + if err != nil { + panic(err) + } + + address := NewRandomAddress(rng) + address.PublicKey = &privateKey.PublicKey + + return &Account{ + addr: address, + privateKey: privateKey, + } +} + // Address returns the account's address. func (acc *Account) Address() wire.Address { return acc.addr @@ -48,20 +65,3 @@ func (acc *Account) Sign(msg []byte) ([]byte, error) { } return signature, nil } - -// NewRandomAccount generates a new random account. -func NewRandomAccount(rng *rand.Rand) *Account { - keySize := 2048 - privateKey, err := rsa.GenerateKey(rng, keySize) - if err != nil { - panic(err) - } - - address := NewRandomAddress(rng) - address.PublicKey = &privateKey.PublicKey - - return &Account{ - addr: address, - privateKey: privateKey, - } -} diff --git a/wire/net/simple/address.go b/wire/net/simple/address.go index c1c53d59f..1ac1ef473 100644 --- a/wire/net/simple/address.go +++ b/wire/net/simple/address.go @@ -20,9 +20,12 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/binary" + "math" "math/big" "math/rand" + "strings" + "github.com/pkg/errors" "perun.network/go-perun/wallet" "perun.network/go-perun/wire" @@ -41,13 +44,32 @@ func NewAddress(host string) wire.Address { } } +// NewRandomAddress returns a new random peer address. +func NewRandomAddress(rng *rand.Rand) *Address { + const addrLen = 32 + l := rng.Intn(addrLen) + d := make([]byte, l) + if _, err := rng.Read(d); err != nil { + panic(err) + } + + a := &Address{ + Name: string(d), + } + return a +} + // MarshalBinary marshals the address to binary. func (a *Address) MarshalBinary() ([]byte, error) { // Initialize a buffer to hold the binary data var buf bytes.Buffer // Encode the length of the name string and the name itself - nameLen := uint16(len(a.Name)) + l := len(a.Name) + if l > math.MaxUint16 { + return nil, errors.New("name length out of bounds") + } + nameLen := uint16(l) if err := binary.Write(&buf, binary.BigEndian, nameLen); err != nil { return nil, err } @@ -110,7 +132,11 @@ func (a *Address) Backend() wallet.BackendID { func encodePublicKey(buf *bytes.Buffer, key *rsa.PublicKey) error { // Encode modulus length and modulus modulusBytes := key.N.Bytes() - modulusLen := uint16(len(modulusBytes)) + l := len(modulusBytes) + if l > math.MaxUint16 { + return errors.New("modulus too large") + } + modulusLen := uint16(l) if err := binary.Write(buf, binary.BigEndian, modulusLen); err != nil { return err } @@ -119,7 +145,11 @@ func encodePublicKey(buf *bytes.Buffer, key *rsa.PublicKey) error { } // Encode public exponent - if err := binary.Write(buf, binary.BigEndian, int32(key.E)); err != nil { + e := key.E + if e < math.MinInt32 || e > math.MaxInt32 { + return errors.New("public exponent too large") + } + if err := binary.Write(buf, binary.BigEndian, int32(e)); err != nil { return err } @@ -181,27 +211,12 @@ func (a *Address) Cmp(b wire.Address) int { } // Compare names - if cmp := bytes.Compare([]byte(a.Name), []byte(bTyped.Name)); cmp != 0 { + if cmp := strings.Compare(a.Name, bTyped.Name); cmp != 0 { return cmp } // Compare binary representations - return bytes.Compare([]byte(a.Name), []byte(bTyped.Name)) -} - -// NewRandomAddress returns a new random peer address. -func NewRandomAddress(rng *rand.Rand) *Address { - const addrLen = 32 - l := rng.Intn(addrLen) - d := make([]byte, l) - if _, err := rng.Read(d); err != nil { - panic(err) - } - - a := &Address{ - Name: string(d), - } - return a + return strings.Compare(a.Name, bTyped.Name) } // NewRandomAddresses returns a new random peer address. diff --git a/wire/net/simple/dialer.go b/wire/net/simple/dialer.go index 546019d70..60c7cc11f 100644 --- a/wire/net/simple/dialer.go +++ b/wire/net/simple/dialer.go @@ -70,14 +70,6 @@ func NewUnixDialer(defaultTimeout time.Duration, tlsConfig *tls.Config) *Dialer return NewNetDialer("unix", defaultTimeout, tlsConfig) } -func (d *Dialer) host(key wire.AddrKey) (string, bool) { - d.mutex.RLock() - defer d.mutex.RUnlock() - - host, ok := d.peers[key] - return host, ok -} - // Dial implements Dialer.Dial(). func (d *Dialer) Dial(ctx context.Context, addr map[wallet.BackendID]wire.Address, ser wire.EnvelopeSerializer) (wirenet.Conn, error) { done := make(chan struct{}) @@ -115,3 +107,11 @@ func (d *Dialer) Register(addr map[wallet.BackendID]wire.Address, address string d.peers[wire.Keys(addr)] = address } + +func (d *Dialer) host(key wire.AddrKey) (string, bool) { + d.mutex.RLock() + defer d.mutex.RUnlock() + + host, ok := d.peers[key] + return host, ok +} diff --git a/wire/net/simple/dialer_internal_test.go b/wire/net/simple/dialer_internal_test.go index 8fcb41596..c366edc96 100644 --- a/wire/net/simple/dialer_internal_test.go +++ b/wire/net/simple/dialer_internal_test.go @@ -22,7 +22,6 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "fmt" "math/big" "net" "testing" @@ -32,6 +31,7 @@ import ( "perun.network/go-perun/wallet" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -47,7 +47,7 @@ func TestNewTCPDialer(t *testing.T) { MinVersion: tls.VersionTLS12, // Set minimum TLS version to TLS 1.2 } d := NewTCPDialer(0, tlsConfig) - assert.Equal(t, d.network, "tcp") + assert.Equal(t, "tcp", d.network) } func TestNewUnixDialer(t *testing.T) { @@ -55,7 +55,7 @@ func TestNewUnixDialer(t *testing.T) { MinVersion: tls.VersionTLS12, // Set minimum TLS version to TLS 1.2 } d := NewUnixDialer(0, tlsConfig) - assert.Equal(t, d.network, "unix") + assert.Equal(t, "unix", d.network) } func TestDialer_Register(t *testing.T) { @@ -74,7 +74,7 @@ func TestDialer_Register(t *testing.T) { host, ok := d.host(key) assert.True(t, ok) - assert.Equal(t, host, "host") + assert.Equal(t, "host", host) } func TestDialer_Dial(t *testing.T) { @@ -108,20 +108,20 @@ func TestDialer_Dial(t *testing.T) { go ct.Stage("accept", func(rt test.ConcT) { conn, err := l.Accept(ser) assert.NoError(t, err) - require.NotNil(rt, conn) + assert.NotNil(rt, conn) re, err := conn.Recv() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, re, e) }) ct.Stage("dial", func(rt test.ConcT) { ctxtest.AssertTerminates(t, timeout, func() { conn, err := d.Dial(context.Background(), laddr, ser) - assert.NoError(t, err) + require.NoError(t, err) require.NotNil(rt, conn) - assert.NoError(t, conn.Send(e)) + require.NoError(t, conn.Send(e)) }) }) @@ -251,7 +251,7 @@ func generateSelfSignedCertConfigs(commonName string, sans []string) (*tls.Confi serverCertPool := x509.NewCertPool() ok := serverCertPool.AppendCertsFromPEM(clientCertPEM) if !ok { - return nil, nil, fmt.Errorf("failed to parse root certificate") + return nil, nil, errors.New("failed to parse root certificate") } // Create the server-side TLS configuration @@ -265,7 +265,7 @@ func generateSelfSignedCertConfigs(commonName string, sans []string) (*tls.Confi clientCertPool := x509.NewCertPool() ok = clientCertPool.AppendCertsFromPEM(serverCertPEM) if !ok { - return nil, nil, fmt.Errorf("failed to parse root certificate") + return nil, nil, errors.New("failed to parse root certificate") } // Create the client-side TLS configuration diff --git a/wire/net/simple/listener_internal_test.go b/wire/net/simple/listener_internal_test.go index b5cc7258b..f37cf0c00 100644 --- a/wire/net/simple/listener_internal_test.go +++ b/wire/net/simple/listener_internal_test.go @@ -31,6 +31,8 @@ const addr = "0.0.0.0:1337" // serverKey and serverCert are generated with the following commands: // openssl ecparam -genkey -name prime256v1 -out server.key // openssl req -new -x509 -key server.key -out server.pem -days 3650. +// +//nolint:gosec const testServerKey = `-----BEGIN EC PARAMETERS----- BggqhkjOPQMBBw== -----END EC PARAMETERS----- @@ -90,7 +92,7 @@ func TestListener_Close(t *testing.T) { t.Run("double close", func(t *testing.T) { l, err := NewTCPListener(addr, tlsConfig) require.NoError(t, err) - assert.NoError(t, l.Close(), "first close must not return error") + require.NoError(t, l.Close(), "first close must not return error") assert.Error(t, l.Close(), "second close must result in error") }) } @@ -104,7 +106,7 @@ func TestNewListener(t *testing.T) { } t.Run("happy", func(t *testing.T) { l, err := NewTCPListener(addr, tlsConfig) - assert.NoError(t, err) + require.NoError(t, err) require.NotNil(t, l) l.Close() }) diff --git a/wire/net/simple/simple_exchange_addr_test.go b/wire/net/simple/simple_exchange_addr_test.go index e78fa8f63..52f9e42c5 100644 --- a/wire/net/simple/simple_exchange_addr_test.go +++ b/wire/net/simple/simple_exchange_addr_test.go @@ -30,6 +30,7 @@ import ( "perun.network/go-perun/wallet" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/wire" wirenet "perun.network/go-perun/wire/net" @@ -68,7 +69,7 @@ func TestExchangeAddrs_Success(t *testing.T) { }() err := wirenet.ExchangeAddrsActive(context.Background(), account0, wire.AddressMapfromAccountMap(account1), conn0) - assert.NoError(t, err) + require.NoError(t, err) wg.Wait() } diff --git a/wire/net/test/connhub_internal_test.go b/wire/net/test/connhub_internal_test.go index edd97b411..de8b1df9b 100644 --- a/wire/net/test/connhub_internal_test.go +++ b/wire/net/test/connhub_internal_test.go @@ -51,7 +51,7 @@ func TestConnHub_Create(t *testing.T) { ct.Stage("accept", func(rt pkgtest.ConcT) { conn, err := l.Accept(ser) assert.NoError(err) - require.NotNil(rt, conn) + assert.NotNil(rt, conn) assert.NoError(conn.Send(wiretest.NewRandomEnvelope(rng, wire.NewPingMsg()))) }) }) diff --git a/wire/net/test/dialer_internal_test.go b/wire/net/test/dialer_internal_test.go index e24748916..d532f1873 100644 --- a/wire/net/test/dialer_internal_test.go +++ b/wire/net/test/dialer_internal_test.go @@ -19,6 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" perunio "perun.network/go-perun/wire/perunio/serializer" "perun.network/go-perun/wire/test" @@ -51,6 +52,6 @@ func TestDialer_Dial(t *testing.T) { func TestDialer_Close(t *testing.T) { var d Dialer - assert.NoError(t, d.Close()) + require.NoError(t, d.Close()) assert.Error(t, d.Close()) } diff --git a/wire/net/test/dialerlist_internal_test.go b/wire/net/test/dialerlist_internal_test.go index 41093a8c1..98a83b439 100644 --- a/wire/net/test/dialerlist_internal_test.go +++ b/wire/net/test/dialerlist_internal_test.go @@ -44,7 +44,7 @@ func TestDialerList_erase(t *testing.T) { d := &Dialer{} l.insert(d) assert.NoError(l.erase(d)) - assert.Len(l.entries, 0) + assert.Empty(l.entries) assert.Error(l.erase(d)) } @@ -55,5 +55,5 @@ func TestDialerList_clear(t *testing.T) { d := &Dialer{} l.insert(d) assert.Equal(l.clear(), []*Dialer{d}) - assert.Len(l.entries, 0) + assert.Empty(l.entries) } diff --git a/wire/net/test/listener_internal_test.go b/wire/net/test/listener_internal_test.go index 87b253cd3..5c2e1140d 100644 --- a/wire/net/test/listener_internal_test.go +++ b/wire/net/test/listener_internal_test.go @@ -20,6 +20,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/wire" wirenet "perun.network/go-perun/wire/net" @@ -49,7 +50,7 @@ func TestListener_Accept_Put(t *testing.T) { ctxtest.AssertTerminates(t, timeout, func() { conn, err := l.Accept(perunio.Serializer()) - assert.NoError(t, err, "Accept must not fail") + require.NoError(t, err, "Accept must not fail") assert.Same(t, connection, conn, "Accept must receive connection from Put") assert.Equal(t, 1, l.NumAccepted(), @@ -130,7 +131,7 @@ func TestListener_Put(t *testing.T) { func TestListener_Close(t *testing.T) { l := NewNetListener() assert.False(t, l.IsClosed()) - assert.NoError(t, l.Close()) + require.NoError(t, l.Close()) assert.True(t, l.IsClosed()) assert.Error(t, l.Close()) } diff --git a/wire/net/test/listenermap_internal_test.go b/wire/net/test/listenermap_internal_test.go index 05eff932e..5fbb7d865 100644 --- a/wire/net/test/listenermap_internal_test.go +++ b/wire/net/test/listenermap_internal_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/wire/test" pkgtest "polycry.pt/poly-go/test" @@ -54,9 +55,9 @@ func TestListenerMap_insert(t *testing.T) { t.Run("insert new", func(t *testing.T) { m := listenerMap{} - for i := 0; i < 10; i++ { + for range 10 { key := test.NewRandomAddress(rng) - assert.NoError(t, m.insert(key, NewNetListener())) + require.NoError(t, m.insert(key, NewNetListener())) _, ok := m.find(key) assert.True(t, ok) } @@ -65,7 +66,7 @@ func TestListenerMap_insert(t *testing.T) { t.Run("double insert", func(t *testing.T) { m := listenerMap{} key := test.NewRandomAddress(rng) - assert.NoError(t, m.insert(key, NewNetListener())) + require.NoError(t, m.insert(key, NewNetListener())) assert.Error(t, m.insert(key, NewNetListener())) }) } @@ -75,10 +76,10 @@ func TestListenerMap_erase(t *testing.T) { t.Run("erase existing", func(t *testing.T) { m := listenerMap{} - for i := 0; i < 10; i++ { + for range 10 { key := test.NewRandomAddress(rng) - assert.NoError(t, m.insert(key, NewNetListener())) - assert.NoError(t, m.erase(key)) + require.NoError(t, m.insert(key, NewNetListener())) + require.NoError(t, m.erase(key)) _, ok := m.find(key) assert.False(t, ok) } diff --git a/wire/perunio/bigint.go b/wire/perunio/bigint.go index 699136434..532eae66d 100644 --- a/wire/perunio/bigint.go +++ b/wire/perunio/bigint.go @@ -51,7 +51,7 @@ func (b *BigInt) Decode(reader io.Reader) error { if b.Int == nil { b.Int = new(big.Int) } - b.Int.SetBytes(bytes) + b.SetBytes(bytes) return nil } @@ -60,7 +60,7 @@ func (b BigInt) Encode(writer io.Writer) error { if b.Int == nil { panic("logic error: tried to encode nil big.Int") } - if b.Int.Sign() == -1 { + if b.Sign() == -1 { panic("encoding of negative big.Int not implemented") } diff --git a/wire/perunio/bigint_external_test.go b/wire/perunio/bigint_external_test.go index 4850cd693..6ff4ff147 100644 --- a/wire/perunio/bigint_external_test.go +++ b/wire/perunio/bigint_external_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/wire/perunio" peruniotest "perun.network/go-perun/wire/perunio/test" ) @@ -46,7 +47,7 @@ func TestBigInt_DecodeZeroLength(t *testing.T) { func TestBigInt_DecodeToExisting(t *testing.T) { x, buf := new(big.Int), bytes.NewBuffer([]byte{1, 42}) wx := perunio.BigInt{Int: x} - assert.NoError(t, wx.Decode(buf), "decoding {1, 42} into big.Int should work") + require.NoError(t, wx.Decode(buf), "decoding {1, 42} into big.Int should work") assert.Zero(t, big.NewInt(42).Cmp(x), "decoding {1, 42} into big.Int should result in 42") } @@ -65,24 +66,24 @@ func TestBigInt_Invalid(t *testing.T) { tooBig := perunio.BigInt{Int: big.NewInt(1)} tooBig.Lsh(tooBig.Int, pos) - a.Error(tooBig.Encode(buf), "encoding too big big.Int should fail") + require.Error(t, tooBig.Encode(buf), "encoding too big big.Int should fail") a.Zero(buf.Len(), "encoding too big big.Int should not have written anything") buf.Reset() // in case above test failed } // manually encode too big number to test failing of decoding buf.Write([]byte{perunio.MaxBigIntLength + 1}) - for i := 0; i < perunio.MaxBigIntLength+1; i++ { + for range perunio.MaxBigIntLength + 1 { buf.WriteByte(0xff) } var result perunio.BigInt - a.Error(result.Decode(buf), "decoding of an integer that is too big should fail") + require.Error(t, result.Decode(buf), "decoding of an integer that is too big should fail") buf.Reset() // Test not sending value, only length buf.WriteByte(1) - a.Error(result.Decode(buf), "decoding after sender only sent length should fail") + require.Error(t, result.Decode(buf), "decoding after sender only sent length should fail") a.Panics(func() { _ = perunio.BigInt{Int: nil}.Encode(buf) }, "encoding nil big.Int failed to panic") } diff --git a/wire/perunio/byteslice_external_test.go b/wire/perunio/byteslice_external_test.go index c90ee62c9..7796283dc 100644 --- a/wire/perunio/byteslice_external_test.go +++ b/wire/perunio/byteslice_external_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/wire/perunio" peruniotest "perun.network/go-perun/wire/perunio/test" @@ -46,7 +47,7 @@ func TestStutter(t *testing.T) { var decodedValue perunio.ByteSlice = make([]byte, len(values)) ctxtest.AssertTerminatesQuickly(t, func() { - assert.NoError(t, decodedValue.Decode(r)) + require.NoError(t, decodedValue.Decode(r)) }) for i, v := range values { assert.Equal(t, decodedValue[i], v) diff --git a/wire/perunio/serialize.go b/wire/perunio/serialize.go index 259e0e805..9c6e2d335 100644 --- a/wire/perunio/serialize.go +++ b/wire/perunio/serialize.go @@ -43,6 +43,8 @@ func Encode(writer io.Writer, values ...interface{}) (err error) { //nolint: cyc err = BigInt{v}.Encode(writer) case [32]byte: _, err = writer.Write(v[:]) + case [256]byte: + _, err = writer.Write(v[:]) case []byte: err = ByteSlice(v).Encode(writer) case string: @@ -86,6 +88,8 @@ func Encode(writer io.Writer, values ...interface{}) (err error) { //nolint: cyc // Decode decodes multiple primitive values from a reader. // All passed values must be references, not copies. +// +//nolint:cyclop func Decode(reader io.Reader, values ...interface{}) (err error) { for i, value := range values { switch v := value.(type) { @@ -101,6 +105,8 @@ func Decode(reader io.Reader, values ...interface{}) (err error) { *v = d.Int case *[32]byte: _, err = io.ReadFull(reader, v[:]) + case *[256]byte: + _, err = io.ReadFull(reader, v[:]) case *[]byte: d := ByteSlice(*v) err = d.Decode(reader) diff --git a/wire/perunio/string.go b/wire/perunio/string.go index 292c0a837..69a42592d 100644 --- a/wire/perunio/string.go +++ b/wire/perunio/string.go @@ -16,19 +16,25 @@ package perunio import ( "encoding/binary" + "fmt" "io" + "math" "github.com/pkg/errors" ) // encodeString writes the length as an uint16 and then the string itself to the io.Writer. func encodeString(w io.Writer, s string) error { - l := uint16(len(s)) - if int(l) != len(s) { + l := len(s) + if l > int(math.MaxUint16) { + return fmt.Errorf("string too long: %d", l) + } + ul := uint16(l) + if int(ul) != len(s) { return errors.Errorf("string length exceeded: %d", len(s)) } - if err := binary.Write(w, byteOrder, l); err != nil { + if err := binary.Write(w, byteOrder, ul); err != nil { return errors.Wrap(err, "failed to write string length") } diff --git a/wire/perunio/string_internal_test.go b/wire/perunio/string_internal_test.go index 4310ec9a8..3016046b3 100644 --- a/wire/perunio/string_internal_test.go +++ b/wire/perunio/string_internal_test.go @@ -46,7 +46,7 @@ func TestEncodeDecodeString(t *testing.T) { }() var d string - assert.NoError(decodeString(r, &d)) + require.NoError(t, decodeString(r, &d)) r.Close() assert.Equal(s, d) <-done @@ -56,7 +56,7 @@ func TestEncodeDecodeString(t *testing.T) { t.Run("too long string", func(t *testing.T) { tooLong := string(append(uint16buf, 42)) //nolint: makezero var buf bytes.Buffer - assert.Error(encodeString(&buf, tooLong)) + require.Error(t, encodeString(&buf, tooLong)) assert.Zero(buf.Len(), "nothing should have been written to the stream") }) @@ -67,7 +67,7 @@ func TestEncodeDecodeString(t *testing.T) { buf.Write(make([]byte, 8)) // 8 bytes missing var d string - assert.Error(decodeString(&buf, &d)) + require.Error(t, decodeString(&buf, &d)) assert.Zero(buf.Len(), "buffer should be exhausted") }) } diff --git a/wire/perunio/wire_internal_test.go b/wire/perunio/wire_internal_test.go index 4d9640a46..e278f45f3 100644 --- a/wire/perunio/wire_internal_test.go +++ b/wire/perunio/wire_internal_test.go @@ -23,6 +23,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" polytest "polycry.pt/poly-go/test" ) @@ -103,7 +104,7 @@ func TestEncodeDecode(t *testing.T) { } } - a.Nil(Decode(r, d...), "failed to decode values") + require.NoError(t, Decode(r, d...), "failed to decode values") for i, v := range values { if !reflect.DeepEqual(reflect.ValueOf(d[i]).Elem().Interface(), v) { diff --git a/wire/protobuf/controlmsgs.go b/wire/protobuf/controlmsgs.go index f363b982f..5e5ca8ae2 100644 --- a/wire/protobuf/controlmsgs.go +++ b/wire/protobuf/controlmsgs.go @@ -46,24 +46,24 @@ func fromAuthResponseMsg(msg *wire.AuthResponseMsg) *Envelope_AuthResponseMsg { func toPingMsg(protoMsg *Envelope_PingMsg) (msg *wire.PingMsg) { msg = &wire.PingMsg{} - msg.Created = time.Unix(0, protoMsg.PingMsg.Created) + msg.Created = time.Unix(0, protoMsg.PingMsg.GetCreated()) return msg } func toPongMsg(protoEnvMsg *Envelope_PongMsg) (msg *wire.PongMsg) { msg = &wire.PongMsg{} - msg.Created = time.Unix(0, protoEnvMsg.PongMsg.Created) + msg.Created = time.Unix(0, protoEnvMsg.PongMsg.GetCreated()) return msg } func toShutdownMsg(protoEnvMsg *Envelope_ShutdownMsg) (msg *wire.ShutdownMsg) { msg = &wire.ShutdownMsg{} - msg.Reason = protoEnvMsg.ShutdownMsg.Reason + msg.Reason = protoEnvMsg.ShutdownMsg.GetReason() return msg } func toAuthResponseMsg(protoEnvMsg *Envelope_AuthResponseMsg) (msg *wire.AuthResponseMsg) { msg = &wire.AuthResponseMsg{} - msg.Signature = protoEnvMsg.AuthResponseMsg.Signature + msg.Signature = protoEnvMsg.AuthResponseMsg.GetSignature() return msg } diff --git a/wire/protobuf/proposalmsgs.go b/wire/protobuf/proposalmsgs.go index 94c51a870..0dc274a1b 100644 --- a/wire/protobuf/proposalmsgs.go +++ b/wire/protobuf/proposalmsgs.go @@ -34,15 +34,15 @@ func ToLedgerChannelProposalMsg(protoEnvMsg *Envelope_LedgerChannelProposalMsg) protoMsg := protoEnvMsg.LedgerChannelProposalMsg msg = &client.LedgerChannelProposalMsg{} - msg.BaseChannelProposal, err = ToBaseChannelProposal(protoMsg.BaseChannelProposal) + msg.BaseChannelProposal, err = ToBaseChannelProposal(protoMsg.GetBaseChannelProposal()) if err != nil { return nil, err } - msg.Participant, err = ToWalletAddr(protoMsg.Participant) + msg.Participant, err = ToWalletAddr(protoMsg.GetParticipant()) if err != nil { return nil, errors.WithMessage(err, "participant address") } - msg.Peers, err = ToWireAddrs(protoMsg.Peers) + msg.Peers, err = ToWireAddrs(protoMsg.GetPeers()) return msg, errors.WithMessage(err, "peers") } @@ -51,8 +51,8 @@ func ToSubChannelProposalMsg(protoEnvMsg *Envelope_SubChannelProposalMsg) (msg * protoMsg := protoEnvMsg.SubChannelProposalMsg msg = &client.SubChannelProposalMsg{} - copy(msg.Parent[:], protoMsg.Parent) - msg.BaseChannelProposal, err = ToBaseChannelProposal(protoMsg.BaseChannelProposal) + copy(msg.Parent[:], protoMsg.GetParent()) + msg.BaseChannelProposal, err = ToBaseChannelProposal(protoMsg.GetBaseChannelProposal()) return msg, err } @@ -62,26 +62,26 @@ func ToVirtualChannelProposalMsg(protoEnvMsg *Envelope_VirtualChannelProposalMsg protoMsg := protoEnvMsg.VirtualChannelProposalMsg msg = &client.VirtualChannelProposalMsg{} - msg.BaseChannelProposal, err = ToBaseChannelProposal(protoMsg.BaseChannelProposal) + msg.BaseChannelProposal, err = ToBaseChannelProposal(protoMsg.GetBaseChannelProposal()) if err != nil { return nil, err } - msg.Proposer, err = ToWalletAddr(protoMsg.Proposer) + msg.Proposer, err = ToWalletAddr(protoMsg.GetProposer()) if err != nil { return nil, errors.WithMessage(err, "proposer") } - msg.Parents = make([]channel.ID, len(protoMsg.Parents)) - for i := range protoMsg.Parents { - copy(msg.Parents[i][:], protoMsg.Parents[i]) + msg.Parents = make([]channel.ID, len(protoMsg.GetParents())) + for i := range protoMsg.GetParents() { + copy(msg.Parents[i][:], protoMsg.GetParents()[i]) } - msg.IndexMaps = make([][]channel.Index, len(protoMsg.IndexMaps)) - for i := range protoMsg.IndexMaps { - msg.IndexMaps[i], err = ToIndexMap(protoMsg.IndexMaps[i].IndexMap) + msg.IndexMaps = make([][]channel.Index, len(protoMsg.GetIndexMaps())) + for i := range protoMsg.GetIndexMaps() { + msg.IndexMaps[i], err = ToIndexMap(protoMsg.GetIndexMaps()[i].GetIndexMap()) if err != nil { return nil, err } } - msg.Peers, err = ToWireAddrs(protoMsg.Peers) + msg.Peers, err = ToWireAddrs(protoMsg.GetPeers()) return msg, errors.WithMessage(err, "peers") } @@ -91,8 +91,8 @@ func ToLedgerChannelProposalAccMsg(protoEnvMsg *Envelope_LedgerChannelProposalAc protoMsg := protoEnvMsg.LedgerChannelProposalAccMsg msg = &client.LedgerChannelProposalAccMsg{} - msg.BaseChannelProposalAcc = ToBaseChannelProposalAcc(protoMsg.BaseChannelProposalAcc) - msg.Participant, err = ToWalletAddr(protoMsg.Participant) + msg.BaseChannelProposalAcc = ToBaseChannelProposalAcc(protoMsg.GetBaseChannelProposalAcc()) + msg.Participant, err = ToWalletAddr(protoMsg.GetParticipant()) return msg, errors.WithMessage(err, "participant") } @@ -102,7 +102,7 @@ func ToSubChannelProposalAccMsg(protoEnvMsg *Envelope_SubChannelProposalAccMsg) protoMsg := protoEnvMsg.SubChannelProposalAccMsg msg = &client.SubChannelProposalAccMsg{} - msg.BaseChannelProposalAcc = ToBaseChannelProposalAcc(protoMsg.BaseChannelProposalAcc) + msg.BaseChannelProposalAcc = ToBaseChannelProposalAcc(protoMsg.GetBaseChannelProposalAcc()) return msg } @@ -112,8 +112,8 @@ func ToVirtualChannelProposalAccMsg(protoEnvMsg *Envelope_VirtualChannelProposal protoMsg := protoEnvMsg.VirtualChannelProposalAccMsg msg = &client.VirtualChannelProposalAccMsg{} - msg.BaseChannelProposalAcc = ToBaseChannelProposalAcc(protoMsg.BaseChannelProposalAcc) - msg.Responder, err = ToWalletAddr(protoMsg.Responder) + msg.BaseChannelProposalAcc = ToBaseChannelProposalAcc(protoMsg.GetBaseChannelProposalAcc()) + msg.Responder, err = ToWalletAddr(protoMsg.GetResponder()) return msg, errors.WithMessage(err, "responder") } @@ -122,21 +122,21 @@ func ToChannelProposalRejMsg(protoEnvMsg *Envelope_ChannelProposalRejMsg) (msg * protoMsg := protoEnvMsg.ChannelProposalRejMsg msg = &client.ChannelProposalRejMsg{} - copy(msg.ProposalID[:], protoMsg.ProposalId) - msg.Reason = protoMsg.Reason + copy(msg.ProposalID[:], protoMsg.GetProposalId()) + msg.Reason = protoMsg.GetReason() return msg } // ToWalletAddr converts a protobuf wallet address to a wallet.Address. func ToWalletAddr(protoAddr *Address) (map[wallet.BackendID]wallet.Address, error) { addrMap := make(map[wallet.BackendID]wallet.Address) - for i := range protoAddr.AddressMapping { + for i := range protoAddr.GetAddressMapping() { var k int32 - if err := binary.Read(bytes.NewReader(protoAddr.AddressMapping[i].Key), binary.BigEndian, &k); err != nil { + if err := binary.Read(bytes.NewReader(protoAddr.GetAddressMapping()[i].GetKey()), binary.BigEndian, &k); err != nil { return nil, fmt.Errorf("failed to read key: %w", err) } addr := wallet.NewAddress(wallet.BackendID(k)) - if err := addr.UnmarshalBinary(protoAddr.AddressMapping[i].Address); err != nil { + if err := addr.UnmarshalBinary(protoAddr.GetAddressMapping()[i].GetAddress()); err != nil { return nil, fmt.Errorf("failed to unmarshal address for key %d: %w", k, err) } @@ -148,13 +148,13 @@ func ToWalletAddr(protoAddr *Address) (map[wallet.BackendID]wallet.Address, erro // ToWireAddr converts a protobuf wallet address to a wallet.Address. func ToWireAddr(protoAddr *Address) (map[wallet.BackendID]wire.Address, error) { addrMap := make(map[wallet.BackendID]wire.Address) - for i := range protoAddr.AddressMapping { + for i := range protoAddr.GetAddressMapping() { var k int32 - if err := binary.Read(bytes.NewReader(protoAddr.AddressMapping[i].Key), binary.BigEndian, &k); err != nil { + if err := binary.Read(bytes.NewReader(protoAddr.GetAddressMapping()[i].GetKey()), binary.BigEndian, &k); err != nil { return nil, fmt.Errorf("failed to read key: %w", err) } addr := wire.NewAddress() - if err := addr.UnmarshalBinary(protoAddr.AddressMapping[i].Address); err != nil { + if err := addr.UnmarshalBinary(protoAddr.GetAddressMapping()[i].GetAddress()); err != nil { return nil, fmt.Errorf("failed to unmarshal address for key %d: %w", k, err) } @@ -191,22 +191,23 @@ func ToWireAddrs(protoAddrs []*Address) ([]map[wallet.BackendID]wire.Address, er // ToBaseChannelProposal converts a protobuf BaseChannelProposal to a client BaseChannelProposal. func ToBaseChannelProposal(protoProp *BaseChannelProposal) (prop client.BaseChannelProposal, err error) { - prop.ChallengeDuration = protoProp.ChallengeDuration - copy(prop.ProposalID[:], protoProp.ProposalId) - copy(prop.NonceShare[:], protoProp.NonceShare) - prop.InitBals, err = ToAllocation(protoProp.InitBals) + prop.ChallengeDuration = protoProp.GetChallengeDuration() + copy(prop.ProposalID[:], protoProp.GetProposalId()) + copy(prop.NonceShare[:], protoProp.GetNonceShare()) + prop.InitBals, err = ToAllocation(protoProp.GetInitBals()) if err != nil { return prop, errors.WithMessage(err, "init bals") } - prop.FundingAgreement = ToBalances(protoProp.FundingAgreement) - prop.App, prop.InitData, err = ToAppAndData(protoProp.App, protoProp.InitData) + prop.FundingAgreement = ToBalances(protoProp.GetFundingAgreement()) + prop.App, prop.InitData, err = ToAppAndData(protoProp.GetApp(), protoProp.GetInitData()) + copy(prop.Aux[:], protoProp.GetAux()) return prop, err } // ToBaseChannelProposalAcc converts a protobuf BaseChannelProposalAcc to a client BaseChannelProposalAcc. func ToBaseChannelProposalAcc(protoPropAcc *BaseChannelProposalAcc) (propAcc client.BaseChannelProposalAcc) { - copy(propAcc.ProposalID[:], protoPropAcc.ProposalId) - copy(propAcc.NonceShare[:], protoPropAcc.NonceShare) + copy(propAcc.ProposalID[:], protoPropAcc.GetProposalId()) + copy(propAcc.NonceShare[:], protoPropAcc.GetNonceShare()) return } @@ -250,7 +251,7 @@ func ToIntSlice(backends [][]byte) ([]wallet.BackendID, error) { ints := make([]wallet.BackendID, len(backends)) for i, backend := range backends { - if len(backend) != 4 { //nolint:gomnd + if len(backend) != 4 { //nolint:mnd return nil, fmt.Errorf("backend %d length is not 4 bytes", i) } @@ -269,43 +270,43 @@ func ToIntSlice(backends [][]byte) ([]wallet.BackendID, error) { // ToAllocation converts a protobuf allocation to a channel.Allocation. func ToAllocation(protoAlloc *Allocation) (alloc *channel.Allocation, err error) { alloc = &channel.Allocation{} - alloc.Backends, err = ToIntSlice(protoAlloc.Backends) + alloc.Backends, err = ToIntSlice(protoAlloc.GetBackends()) if err != nil { return nil, errors.WithMessage(err, "backends") } - alloc.Assets = make([]channel.Asset, len(protoAlloc.Assets)) - for i := range protoAlloc.Assets { + alloc.Assets = make([]channel.Asset, len(protoAlloc.GetAssets())) + for i := range protoAlloc.GetAssets() { alloc.Assets[i] = channel.NewAsset(alloc.Backends[i]) - err = alloc.Assets[i].UnmarshalBinary(protoAlloc.Assets[i]) + err = alloc.Assets[i].UnmarshalBinary(protoAlloc.GetAssets()[i]) if err != nil { return nil, errors.WithMessagef(err, "%d'th asset", i) } } - alloc.Locked = make([]channel.SubAlloc, len(protoAlloc.Locked)) - for i := range protoAlloc.Locked { - alloc.Locked[i], err = ToSubAlloc(protoAlloc.Locked[i]) + alloc.Locked = make([]channel.SubAlloc, len(protoAlloc.GetLocked())) + for i := range protoAlloc.GetLocked() { + alloc.Locked[i], err = ToSubAlloc(protoAlloc.GetLocked()[i]) if err != nil { return nil, errors.WithMessagef(err, "%d'th sub alloc", i) } } - alloc.Balances = ToBalances(protoAlloc.Balances) + alloc.Balances = ToBalances(protoAlloc.GetBalances()) return alloc, nil } // ToBalances converts a protobuf Balances to a channel.Balances. func ToBalances(protoBalances *Balances) (balances channel.Balances) { - balances = make([][]channel.Bal, len(protoBalances.Balances)) - for i := range protoBalances.Balances { - balances[i] = ToBalance(protoBalances.Balances[i]) + balances = make([][]channel.Bal, len(protoBalances.GetBalances())) + for i := range protoBalances.GetBalances() { + balances[i] = ToBalance(protoBalances.GetBalances()[i]) } return balances } // ToBalance converts a protobuf Balance to a channel.Bal. func ToBalance(protoBalance *Balance) (balance []channel.Bal) { - balance = make([]channel.Bal, len(protoBalance.Balance)) - for j := range protoBalance.Balance { - balance[j] = new(big.Int).SetBytes(protoBalance.Balance[j]) + balance = make([]channel.Bal, len(protoBalance.GetBalance())) + for j := range protoBalance.GetBalance() { + balance[j] = new(big.Int).SetBytes(protoBalance.GetBalance()[j]) } return balance } @@ -313,12 +314,12 @@ func ToBalance(protoBalance *Balance) (balance []channel.Bal) { // ToSubAlloc converts a protobuf SubAlloc to a channel.SubAlloc. func ToSubAlloc(protoSubAlloc *SubAlloc) (subAlloc channel.SubAlloc, err error) { subAlloc = channel.SubAlloc{} - subAlloc.Bals = ToBalance(protoSubAlloc.Bals) - if len(protoSubAlloc.Id) != len(subAlloc.ID) { + subAlloc.Bals = ToBalance(protoSubAlloc.GetBals()) + if len(protoSubAlloc.GetId()) != len(subAlloc.ID) { return subAlloc, errors.New("sub alloc id has incorrect length") } - copy(subAlloc.ID[:], protoSubAlloc.Id) - subAlloc.IndexMap, err = ToIndexMap(protoSubAlloc.IndexMap.IndexMap) + copy(subAlloc.ID[:], protoSubAlloc.GetId()) + subAlloc.IndexMap, err = ToIndexMap(protoSubAlloc.GetIndexMap().GetIndexMap()) return subAlloc, err } @@ -327,9 +328,13 @@ func ToIndexMap(protoIndexMap []uint32) (indexMap []channel.Index, err error) { indexMap = make([]channel.Index, len(protoIndexMap)) for i := range protoIndexMap { if protoIndexMap[i] > math.MaxUint16 { - return nil, fmt.Errorf("%d'th index is invalid", i) //nolint:goerr113 // We do not want to define this as constant error. + return nil, fmt.Errorf("%d'th index is invalid", i) // We do not want to define this as constant error. } - indexMap[i] = channel.Index(uint16(protoIndexMap[i])) + val := protoIndexMap[i] + if val > math.MaxUint16 { + return indexMap, fmt.Errorf("index too large: %d", val) + } + indexMap[i] = channel.Index(uint16(val)) } return indexMap, nil } @@ -354,7 +359,7 @@ func FromLedgerChannelProposalMsg(msg *client.LedgerChannelProposalMsg) (_ *Enve func FromSubChannelProposalMsg(msg *client.SubChannelProposalMsg) (_ *Envelope_SubChannelProposalMsg, err error) { protoMsg := &SubChannelProposalMsg{} protoMsg.Parent = make([]byte, len(msg.Parent)) - copy(protoMsg.Parent, msg.Parent[:]) + copy(protoMsg.GetParent(), msg.Parent[:]) protoMsg.BaseChannelProposal, err = FromBaseChannelProposal(msg.BaseChannelProposal) return &Envelope_SubChannelProposalMsg{protoMsg}, err } @@ -374,7 +379,7 @@ func FromVirtualChannelProposalMsg(msg *client.VirtualChannelProposalMsg) (_ *En protoMsg.Parents = make([][]byte, len(msg.Parents)) for i := range msg.Parents { protoMsg.Parents[i] = make([]byte, len(msg.Parents[i])) - copy(protoMsg.Parents[i], msg.Parents[i][:]) + copy(protoMsg.GetParents()[i], msg.Parents[i][:]) } protoMsg.IndexMaps = make([]*IndexMap, len(msg.IndexMaps)) for i := range msg.IndexMaps { @@ -414,7 +419,7 @@ func FromVirtualChannelProposalAccMsg(msg *client.VirtualChannelProposalAccMsg) func FromChannelProposalRejMsg(msg *client.ChannelProposalRejMsg) (_ *Envelope_ChannelProposalRejMsg) { protoMsg := &ChannelProposalRejMsg{} protoMsg.ProposalId = make([]byte, len(msg.ProposalID)) - copy(protoMsg.ProposalId, msg.ProposalID[:]) + copy(protoMsg.GetProposalId(), msg.ProposalID[:]) protoMsg.Reason = msg.Reason return &Envelope_ChannelProposalRejMsg{protoMsg} } @@ -424,8 +429,12 @@ func FromWalletAddr(addr map[wallet.BackendID]wallet.Address) (*Address, error) var addressMappings []*AddressMapping //nolint:prealloc for key, address := range addr { - keyBytes := make([]byte, 4) //nolint:gomnd - binary.BigEndian.PutUint32(keyBytes, uint32(key)) + keyBytes := make([]byte, 4) //nolint:mnd + keyInt := int(key) + if keyInt < 0 || keyInt > math.MaxUint32 { + panic("Key exceeds uint32 range") + } + binary.BigEndian.PutUint32(keyBytes, uint32(keyInt)) addressBytes, err := address.MarshalBinary() if err != nil { @@ -448,8 +457,12 @@ func FromWireAddr(addr map[wallet.BackendID]wire.Address) (*Address, error) { var addressMappings []*AddressMapping //nolint:prealloc for key, address := range addr { - keyBytes := make([]byte, 4) //nolint:gomnd - binary.BigEndian.PutUint32(keyBytes, uint32(key)) + keyBytes := make([]byte, 4) //nolint:mnd + keyInt := int(key) + if keyInt < 0 || keyInt > math.MaxUint32 { + panic("Key exceeds uint32 range") + } + binary.BigEndian.PutUint32(keyBytes, uint32(keyInt)) addressBytes, err := address.MarshalBinary() if err != nil { @@ -496,10 +509,13 @@ func FromBaseChannelProposal(prop client.BaseChannelProposal) (protoProp *BaseCh protoProp = &BaseChannelProposal{} protoProp.ProposalId = make([]byte, len(prop.ProposalID)) - copy(protoProp.ProposalId, prop.ProposalID[:]) + copy(protoProp.GetProposalId(), prop.ProposalID[:]) protoProp.NonceShare = make([]byte, len(prop.NonceShare)) - copy(protoProp.NonceShare, prop.NonceShare[:]) + copy(protoProp.GetNonceShare(), prop.NonceShare[:]) + + protoProp.Aux = make([]byte, len(prop.Aux)) + copy(protoProp.GetAux(), prop.Aux[:]) protoProp.ChallengeDuration = prop.ChallengeDuration @@ -520,8 +536,8 @@ func FromBaseChannelProposalAcc(propAcc client.BaseChannelProposalAcc) (protoPro protoPropAcc = &BaseChannelProposalAcc{} protoPropAcc.ProposalId = make([]byte, len(propAcc.ProposalID)) protoPropAcc.NonceShare = make([]byte, len(propAcc.NonceShare)) - copy(protoPropAcc.ProposalId, propAcc.ProposalID[:]) - copy(protoPropAcc.NonceShare, propAcc.NonceShare[:]) + copy(protoPropAcc.GetProposalId(), propAcc.ProposalID[:]) + copy(protoPropAcc.GetNonceShare(), propAcc.NonceShare[:]) return protoPropAcc } @@ -552,8 +568,12 @@ func FromAllocation(alloc channel.Allocation) (protoAlloc *Allocation, err error protoAlloc = &Allocation{} protoAlloc.Backends = make([][]byte, len(alloc.Backends)) for i := range alloc.Backends { - protoAlloc.Backends[i] = make([]byte, 4) //nolint:gomnd - binary.BigEndian.PutUint32(protoAlloc.Backends[i], uint32(alloc.Backends[i])) + protoAlloc.Backends[i] = make([]byte, 4) //nolint:mnd + id := int(alloc.Backends[i]) + if id < 0 || id > math.MaxUint32 { + panic("BackendID exceeds uint32 range") + } + binary.BigEndian.PutUint32(protoAlloc.GetBackends()[i], uint32(id)) } protoAlloc.Assets = make([][]byte, len(alloc.Assets)) for i := range alloc.Assets { @@ -594,10 +614,10 @@ func FromBalance(balance []channel.Bal) (protoBalance *Balance, err error) { } for i := range balance { if balance[i] == nil { - return nil, fmt.Errorf("%d'th amount is nil", i) //nolint:goerr113 // We do not want to define this as constant error. + return nil, fmt.Errorf("%d'th amount is nil", i) // We do not want to define this as constant error. } if balance[i].Sign() == -1 { - return nil, fmt.Errorf("%d'th amount is negative", i) //nolint:goerr113 // We do not want to define this as constant error. + return nil, fmt.Errorf("%d'th amount is negative", i) // We do not want to define this as constant error. } protoBalance.Balance[i] = balance[i].Bytes() } @@ -608,7 +628,7 @@ func FromBalance(balance []channel.Bal) (protoBalance *Balance, err error) { func FromSubAlloc(subAlloc channel.SubAlloc) (protoSubAlloc *SubAlloc, err error) { protoSubAlloc = &SubAlloc{} protoSubAlloc.Id = make([]byte, len(subAlloc.ID)) - copy(protoSubAlloc.Id, subAlloc.ID[:]) + copy(protoSubAlloc.GetId(), subAlloc.ID[:]) protoSubAlloc.IndexMap = &IndexMap{IndexMap: FromIndexMap(subAlloc.IndexMap)} protoSubAlloc.Bals, err = FromBalance(subAlloc.Bals) return protoSubAlloc, err diff --git a/wire/protobuf/serializer.go b/wire/protobuf/serializer.go index 9d13d2351..8d26fbf55 100644 --- a/wire/protobuf/serializer.go +++ b/wire/protobuf/serializer.go @@ -18,6 +18,7 @@ import ( "encoding/binary" "fmt" "io" + "math" "perun.network/go-perun/wallet" @@ -75,7 +76,6 @@ func (serializer) Encode(w io.Writer, env *wire.Envelope) (err error) { //nolint case *client.ChannelSyncMsg: protoEnv.Msg, err = fromChannelSyncMsg(msg) default: - //nolint: goerr113 // We do not want to define this as constant error. err = fmt.Errorf("unknown message type: %T", msg) } if err != nil { @@ -104,7 +104,11 @@ func writeEnvelope(w io.Writer, env *Envelope) error { if err != nil { return errors.Wrap(err, "marshalling envelope") } - if err := binary.Write(w, binary.BigEndian, uint16(len(data))); err != nil { + l := len(data) + if l > math.MaxUint16 { + return fmt.Errorf("envelope length out of bounds: %d", l) + } + if err := binary.Write(w, binary.BigEndian, uint16(l)); err != nil { return errors.Wrap(err, "writing length to wire") } _, err = w.Write(data) @@ -127,7 +131,7 @@ func (serializer) Decode(r io.Reader) (env *wire.Envelope, err error) { //nolint return nil, err } - switch protoMsg := protoEnv.Msg.(type) { + switch protoMsg := protoEnv.GetMsg().(type) { case *Envelope_PingMsg: env.Msg = toPingMsg(protoMsg) case *Envelope_PongMsg: @@ -163,7 +167,6 @@ func (serializer) Decode(r io.Reader) (env *wire.Envelope, err error) { //nolint case *Envelope_ChannelSyncMsg: env.Msg, err = toChannelSyncMsg(protoMsg) default: - //nolint: goerr113 // We do not want to define this as constant error. err = fmt.Errorf("unknown message type: %T", protoMsg) } @@ -184,13 +187,13 @@ func readEnvelope(r io.Reader) (*Envelope, error) { } func unmarshalSenderRecipient(protoEnv *Envelope) (map[wallet.BackendID]wire.Address, map[wallet.BackendID]wire.Address, error) { - sender, err := ToWireAddr(protoEnv.Sender) + sender, err := ToWireAddr(protoEnv.GetSender()) if err != nil { return nil, nil, errors.Wrap(err, "unmarshalling sender address") } - recipient, err1 := ToWireAddr(protoEnv.Recipient) + recipient, err1 := ToWireAddr(protoEnv.GetRecipient()) if err1 != nil { - return nil, nil, errors.Wrap(err, "unmarshalling recipient address") + return nil, nil, errors.Wrap(err1, "unmarshalling recipient address") } return sender, recipient, nil } diff --git a/wire/protobuf/syncmsgs.go b/wire/protobuf/syncmsgs.go index fb94a5b19..ee172ab8b 100644 --- a/wire/protobuf/syncmsgs.go +++ b/wire/protobuf/syncmsgs.go @@ -15,6 +15,9 @@ package protobuf import ( + "fmt" + "math" + "perun.network/go-perun/channel" "perun.network/go-perun/client" ) @@ -23,13 +26,17 @@ func toChannelSyncMsg(protoEnvMsg *Envelope_ChannelSyncMsg) (msg *client.Channel protoMsg := protoEnvMsg.ChannelSyncMsg msg = &client.ChannelSyncMsg{} - msg.Phase = channel.Phase(protoMsg.Phase) - msg.CurrentTX.Sigs = make([][]byte, len(protoMsg.CurrentTx.Sigs)) - for i := range protoMsg.CurrentTx.Sigs { - msg.CurrentTX.Sigs[i] = make([]byte, len(protoMsg.CurrentTx.Sigs[i])) - copy(msg.CurrentTX.Sigs[i], protoMsg.CurrentTx.Sigs[i]) + phase := protoMsg.GetPhase() + if phase > math.MaxUint8 { + return msg, fmt.Errorf("invalid phase: %d", phase) + } + msg.Phase = channel.Phase(phase) + msg.CurrentTX.Sigs = make([][]byte, len(protoMsg.GetCurrentTx().GetSigs())) + for i := range protoMsg.GetCurrentTx().GetSigs() { + msg.CurrentTX.Sigs[i] = make([]byte, len(protoMsg.GetCurrentTx().GetSigs()[i])) + copy(msg.CurrentTX.Sigs[i], protoMsg.GetCurrentTx().GetSigs()[i]) } - msg.CurrentTX.State, err = ToState(protoMsg.CurrentTx.State) + msg.CurrentTX.State, err = ToState(protoMsg.GetCurrentTx().GetState()) return msg, err } @@ -41,7 +48,7 @@ func fromChannelSyncMsg(msg *client.ChannelSyncMsg) (_ *Envelope_ChannelSyncMsg, protoMsg.CurrentTx.Sigs = make([][]byte, len(msg.CurrentTX.Sigs)) for i := range msg.CurrentTX.Sigs { protoMsg.CurrentTx.Sigs[i] = make([]byte, len(msg.CurrentTX.Sigs[i])) - copy(protoMsg.CurrentTx.Sigs[i], msg.CurrentTX.Sigs[i]) + copy(protoMsg.GetCurrentTx().GetSigs()[i], msg.CurrentTX.Sigs[i]) } protoMsg.CurrentTx.State, err = FromState(msg.CurrentTX.State) return &Envelope_ChannelSyncMsg{protoMsg}, err diff --git a/wire/protobuf/test/serializertest.go b/wire/protobuf/test/serializertest.go index 7488d177b..172362c12 100644 --- a/wire/protobuf/test/serializertest.go +++ b/wire/protobuf/test/serializertest.go @@ -42,7 +42,7 @@ func MsgSerializerTest(t *testing.T, msg wire.Msg) { gotEnvelope, err := ser.Decode(&buff) require.NoError(t, err) - assert.EqualValues(t, envelope, gotEnvelope) + assert.Equal(t, envelope, gotEnvelope) } func newEnvelope(rng *rand.Rand) *wire.Envelope { diff --git a/wire/protobuf/updatemsgs.go b/wire/protobuf/updatemsgs.go index 8834312d1..62fdf8b24 100644 --- a/wire/protobuf/updatemsgs.go +++ b/wire/protobuf/updatemsgs.go @@ -15,6 +15,7 @@ package protobuf import ( + "fmt" "math" "math/big" @@ -38,15 +39,15 @@ func ToVirtualChannelFundingProposalMsg(protoEnvMsg *Envelope_VirtualChannelFund protoMsg := protoEnvMsg.VirtualChannelFundingProposalMsg msg = &client.VirtualChannelFundingProposalMsg{} - msg.Initial, err = ToSignedState(protoMsg.Initial) + msg.Initial, err = ToSignedState(protoMsg.GetInitial()) if err != nil { return nil, errors.WithMessage(err, "initial state") } - msg.IndexMap, err = ToIndexMap(protoMsg.IndexMap.IndexMap) + msg.IndexMap, err = ToIndexMap(protoMsg.GetIndexMap().GetIndexMap()) if err != nil { return nil, err } - msg.ChannelUpdateMsg, err = ToChannelUpdate(protoMsg.ChannelUpdateMsg) + msg.ChannelUpdateMsg, err = ToChannelUpdate(protoMsg.GetChannelUpdateMsg()) return msg, err } @@ -59,11 +60,11 @@ func ToVirtualChannelSettlementProposalMsg(protoEnvMsg *Envelope_VirtualChannelS protoMsg := protoEnvMsg.VirtualChannelSettlementProposalMsg msg = &client.VirtualChannelSettlementProposalMsg{} - msg.Final, err = ToSignedState(protoMsg.Final) + msg.Final, err = ToSignedState(protoMsg.GetFinal()) if err != nil { return nil, errors.WithMessage(err, "final state") } - msg.ChannelUpdateMsg, err = ToChannelUpdate(protoMsg.ChannelUpdateMsg) + msg.ChannelUpdateMsg, err = ToChannelUpdate(protoMsg.GetChannelUpdateMsg()) return msg, err } @@ -72,10 +73,10 @@ func ToChannelUpdateAccMsg(protoEnvMsg *Envelope_ChannelUpdateAccMsg) (msg *clie protoMsg := protoEnvMsg.ChannelUpdateAccMsg msg = &client.ChannelUpdateAccMsg{} - copy(msg.ChannelID[:], protoMsg.ChannelId) - msg.Version = protoMsg.Version - msg.Sig = make([]byte, len(protoMsg.Sig)) - copy(msg.Sig, protoMsg.Sig) + copy(msg.ChannelID[:], protoMsg.GetChannelId()) + msg.Version = protoMsg.GetVersion() + msg.Sig = make([]byte, len(protoMsg.GetSig())) + copy(msg.Sig, protoMsg.GetSig()) return msg } @@ -84,56 +85,66 @@ func ToChannelUpdateRejMsg(protoEnvMsg *Envelope_ChannelUpdateRejMsg) (msg *clie protoMsg := protoEnvMsg.ChannelUpdateRejMsg msg = &client.ChannelUpdateRejMsg{} - copy(msg.ChannelID[:], protoMsg.ChannelId) - msg.Version = protoMsg.Version - msg.Reason = protoMsg.Reason + copy(msg.ChannelID[:], protoMsg.GetChannelId()) + msg.Version = protoMsg.GetVersion() + msg.Reason = protoMsg.GetReason() return msg } // ToChannelUpdate parses protobuf channel updates. func ToChannelUpdate(protoUpdate *ChannelUpdateMsg) (update client.ChannelUpdateMsg, err error) { - if protoUpdate.ChannelUpdate.ActorIdx > math.MaxUint16 { + if protoUpdate.GetChannelUpdate().GetActorIdx() > math.MaxUint16 { return update, errors.New("actor index is invalid") } - update.ActorIdx = channel.Index(protoUpdate.ChannelUpdate.ActorIdx) - update.Sig = make([]byte, len(protoUpdate.Sig)) - copy(update.Sig, protoUpdate.Sig) - update.State, err = ToState(protoUpdate.ChannelUpdate.State) + idx := protoUpdate.GetChannelUpdate().GetActorIdx() + if idx > math.MaxUint16 { + return update, fmt.Errorf("invalid actor index: %d", idx) + } + update.ActorIdx = channel.Index(uint16(idx)) + + update.Sig = make([]byte, len(protoUpdate.GetSig())) + copy(update.Sig, protoUpdate.GetSig()) + update.State, err = ToState(protoUpdate.GetChannelUpdate().GetState()) return update, err } // ToSignedState converts a protobuf SignedState to a channel.SignedState. func ToSignedState(protoSignedState *SignedState) (signedState channel.SignedState, err error) { - signedState.Params, err = ToParams(protoSignedState.Params) + signedState.Params, err = ToParams(protoSignedState.GetParams()) if err != nil { return signedState, err } - signedState.Sigs = make([][]byte, len(protoSignedState.Sigs)) - for i := range protoSignedState.Sigs { - signedState.Sigs[i] = make([]byte, len(protoSignedState.Sigs[i])) - copy(signedState.Sigs[i], protoSignedState.Sigs[i]) + signedState.Sigs = make([][]byte, len(protoSignedState.GetSigs())) + for i := range protoSignedState.GetSigs() { + signedState.Sigs[i] = make([]byte, len(protoSignedState.GetSigs()[i])) + copy(signedState.Sigs[i], protoSignedState.GetSigs()[i]) } - signedState.State, err = ToState(protoSignedState.State) + signedState.State, err = ToState(protoSignedState.GetState()) return signedState, err } // ToParams converts a protobuf Params to a channel.Params. func ToParams(protoParams *Params) (*channel.Params, error) { - app, err := ToApp(protoParams.App) + app, err := ToApp(protoParams.GetApp()) if err != nil { return nil, err } - parts, err := ToWalletAddrs(protoParams.Parts) + parts, err := ToWalletAddrs(protoParams.GetParts()) if err != nil { return nil, errors.WithMessage(err, "parts") } + + var aux channel.Aux + copy(aux[:], protoParams.GetAux()) params := channel.NewParamsUnsafe( - protoParams.ChallengeDuration, + protoParams.GetChallengeDuration(), parts, app, - (new(big.Int)).SetBytes(protoParams.Nonce), - protoParams.LedgerChannel, - protoParams.VirtualChannel) + (new(big.Int)).SetBytes(protoParams.GetNonce()), + protoParams.GetLedgerChannel(), + protoParams.GetVirtualChannel(), + aux, + ) return params, nil } @@ -141,15 +152,15 @@ func ToParams(protoParams *Params) (*channel.Params, error) { // ToState converts a protobuf State to a channel.State. func ToState(protoState *State) (state *channel.State, err error) { state = &channel.State{} - copy(state.ID[:], protoState.Id) - state.Version = protoState.Version - state.IsFinal = protoState.IsFinal - allocation, err := ToAllocation(protoState.Allocation) + copy(state.ID[:], protoState.GetId()) + state.Version = protoState.GetVersion() + state.IsFinal = protoState.GetIsFinal() + allocation, err := ToAllocation(protoState.GetAllocation()) if err != nil { return nil, errors.WithMessage(err, "allocation") } state.Allocation = *allocation - state.App, state.Data, err = ToAppAndData(protoState.App, protoState.Data) + state.App, state.Data, err = ToAppAndData(protoState.GetApp(), protoState.GetData()) return state, err } @@ -197,9 +208,9 @@ func FromChannelUpdateAccMsg(msg *client.ChannelUpdateAccMsg) *Envelope_ChannelU protoMsg := &ChannelUpdateAccMsg{} protoMsg.ChannelId = make([]byte, len(msg.ChannelID)) - copy(protoMsg.ChannelId, msg.ChannelID[:]) + copy(protoMsg.GetChannelId(), msg.ChannelID[:]) protoMsg.Sig = make([]byte, len(msg.Sig)) - copy(protoMsg.Sig, msg.Sig) + copy(protoMsg.GetSig(), msg.Sig) protoMsg.Version = msg.Version return &Envelope_ChannelUpdateAccMsg{protoMsg} } @@ -208,7 +219,7 @@ func FromChannelUpdateAccMsg(msg *client.ChannelUpdateAccMsg) *Envelope_ChannelU func FromChannelUpdateRejMsg(msg *client.ChannelUpdateRejMsg) *Envelope_ChannelUpdateRejMsg { protoMsg := &ChannelUpdateRejMsg{} protoMsg.ChannelId = make([]byte, len(msg.ChannelID)) - copy(protoMsg.ChannelId, msg.ChannelID[:]) + copy(protoMsg.GetChannelId(), msg.ChannelID[:]) protoMsg.Version = msg.Version protoMsg.Reason = msg.Reason return &Envelope_ChannelUpdateRejMsg{protoMsg} @@ -219,10 +230,10 @@ func FromChannelUpdate(update *client.ChannelUpdateMsg) (protoUpdate *ChannelUpd protoUpdate = &ChannelUpdateMsg{} protoUpdate.ChannelUpdate = &ChannelUpdate{} - protoUpdate.ChannelUpdate.ActorIdx = uint32(update.ChannelUpdate.ActorIdx) + protoUpdate.ChannelUpdate.ActorIdx = uint32(update.ActorIdx) protoUpdate.Sig = make([]byte, len(update.Sig)) - copy(protoUpdate.Sig, update.Sig) - protoUpdate.ChannelUpdate.State, err = FromState(update.ChannelUpdate.State) + copy(protoUpdate.GetSig(), update.Sig) + protoUpdate.ChannelUpdate.State, err = FromState(update.State) return protoUpdate, err } @@ -232,7 +243,7 @@ func FromSignedState(signedState *channel.SignedState) (protoSignedState *Signed protoSignedState.Sigs = make([][]byte, len(signedState.Sigs)) for i := range signedState.Sigs { protoSignedState.Sigs[i] = make([]byte, len(signedState.Sigs[i])) - copy(protoSignedState.Sigs[i], signedState.Sigs[i]) + copy(protoSignedState.GetSigs()[i], signedState.Sigs[i]) } protoSignedState.Params, err = FromParams(signedState.Params) if err != nil { @@ -255,6 +266,7 @@ func FromParams(params *channel.Params) (protoParams *Params, err error) { return nil, errors.WithMessage(err, "parts") } protoParams.App, err = FromApp(params.App) + protoParams.Aux = params.Aux[:] return protoParams, err } @@ -263,7 +275,7 @@ func FromState(state *channel.State) (protoState *State, err error) { protoState = &State{} protoState.Id = make([]byte, len(state.ID)) - copy(protoState.Id, state.ID[:]) + copy(protoState.GetId(), state.ID[:]) protoState.Version = state.Version protoState.IsFinal = state.IsFinal protoState.Allocation, err = FromAllocation(state.Allocation) diff --git a/wire/protobuf/wire.pb.go b/wire/protobuf/wire.pb.go index afdb9fa52..9d46e63a2 100644 --- a/wire/protobuf/wire.pb.go +++ b/wire/protobuf/wire.pb.go @@ -16,18 +16,18 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v3.20.3 -// source: wire.proto +// protoc-gen-go v1.36.6 +// protoc v6.30.2 +// source: wire/protobuf/wire.proto package protobuf import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" ) const ( @@ -40,17 +40,14 @@ const ( // Envelope encapsulates a message with the routing information. That is the // the sender and the intended receiver. type Envelope struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // sender of the message. Sender *Address `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` // intended recipient of the message. Recipient *Address `protobuf:"bytes,2,opt,name=recipient,proto3" json:"recipient,omitempty"` // msg should contain on the valid message types. // - // Types that are assignable to Msg: + // Types that are valid to be assigned to Msg: // // *Envelope_PingMsg // *Envelope_PongMsg @@ -69,16 +66,16 @@ type Envelope struct { // *Envelope_ChannelUpdateAccMsg // *Envelope_ChannelUpdateRejMsg // *Envelope_ChannelSyncMsg - Msg isEnvelope_Msg `protobuf_oneof:"msg"` + Msg isEnvelope_Msg `protobuf_oneof:"msg"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Envelope) Reset() { *x = Envelope{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Envelope) String() string { @@ -88,8 +85,8 @@ func (x *Envelope) String() string { func (*Envelope) ProtoMessage() {} func (x *Envelope) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[0] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -101,7 +98,7 @@ func (x *Envelope) ProtoReflect() protoreflect.Message { // Deprecated: Use Envelope.ProtoReflect.Descriptor instead. func (*Envelope) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{0} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{0} } func (x *Envelope) GetSender() *Address { @@ -118,128 +115,162 @@ func (x *Envelope) GetRecipient() *Address { return nil } -func (m *Envelope) GetMsg() isEnvelope_Msg { - if m != nil { - return m.Msg +func (x *Envelope) GetMsg() isEnvelope_Msg { + if x != nil { + return x.Msg } return nil } func (x *Envelope) GetPingMsg() *PingMsg { - if x, ok := x.GetMsg().(*Envelope_PingMsg); ok { - return x.PingMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_PingMsg); ok { + return x.PingMsg + } } return nil } func (x *Envelope) GetPongMsg() *PongMsg { - if x, ok := x.GetMsg().(*Envelope_PongMsg); ok { - return x.PongMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_PongMsg); ok { + return x.PongMsg + } } return nil } func (x *Envelope) GetShutdownMsg() *ShutdownMsg { - if x, ok := x.GetMsg().(*Envelope_ShutdownMsg); ok { - return x.ShutdownMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_ShutdownMsg); ok { + return x.ShutdownMsg + } } return nil } func (x *Envelope) GetAuthResponseMsg() *AuthResponseMsg { - if x, ok := x.GetMsg().(*Envelope_AuthResponseMsg); ok { - return x.AuthResponseMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_AuthResponseMsg); ok { + return x.AuthResponseMsg + } } return nil } func (x *Envelope) GetLedgerChannelProposalMsg() *LedgerChannelProposalMsg { - if x, ok := x.GetMsg().(*Envelope_LedgerChannelProposalMsg); ok { - return x.LedgerChannelProposalMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_LedgerChannelProposalMsg); ok { + return x.LedgerChannelProposalMsg + } } return nil } func (x *Envelope) GetLedgerChannelProposalAccMsg() *LedgerChannelProposalAccMsg { - if x, ok := x.GetMsg().(*Envelope_LedgerChannelProposalAccMsg); ok { - return x.LedgerChannelProposalAccMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_LedgerChannelProposalAccMsg); ok { + return x.LedgerChannelProposalAccMsg + } } return nil } func (x *Envelope) GetSubChannelProposalMsg() *SubChannelProposalMsg { - if x, ok := x.GetMsg().(*Envelope_SubChannelProposalMsg); ok { - return x.SubChannelProposalMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_SubChannelProposalMsg); ok { + return x.SubChannelProposalMsg + } } return nil } func (x *Envelope) GetSubChannelProposalAccMsg() *SubChannelProposalAccMsg { - if x, ok := x.GetMsg().(*Envelope_SubChannelProposalAccMsg); ok { - return x.SubChannelProposalAccMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_SubChannelProposalAccMsg); ok { + return x.SubChannelProposalAccMsg + } } return nil } func (x *Envelope) GetVirtualChannelProposalMsg() *VirtualChannelProposalMsg { - if x, ok := x.GetMsg().(*Envelope_VirtualChannelProposalMsg); ok { - return x.VirtualChannelProposalMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_VirtualChannelProposalMsg); ok { + return x.VirtualChannelProposalMsg + } } return nil } func (x *Envelope) GetVirtualChannelProposalAccMsg() *VirtualChannelProposalAccMsg { - if x, ok := x.GetMsg().(*Envelope_VirtualChannelProposalAccMsg); ok { - return x.VirtualChannelProposalAccMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_VirtualChannelProposalAccMsg); ok { + return x.VirtualChannelProposalAccMsg + } } return nil } func (x *Envelope) GetChannelProposalRejMsg() *ChannelProposalRejMsg { - if x, ok := x.GetMsg().(*Envelope_ChannelProposalRejMsg); ok { - return x.ChannelProposalRejMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_ChannelProposalRejMsg); ok { + return x.ChannelProposalRejMsg + } } return nil } func (x *Envelope) GetChannelUpdateMsg() *ChannelUpdateMsg { - if x, ok := x.GetMsg().(*Envelope_ChannelUpdateMsg); ok { - return x.ChannelUpdateMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_ChannelUpdateMsg); ok { + return x.ChannelUpdateMsg + } } return nil } func (x *Envelope) GetVirtualChannelFundingProposalMsg() *VirtualChannelFundingProposalMsg { - if x, ok := x.GetMsg().(*Envelope_VirtualChannelFundingProposalMsg); ok { - return x.VirtualChannelFundingProposalMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_VirtualChannelFundingProposalMsg); ok { + return x.VirtualChannelFundingProposalMsg + } } return nil } func (x *Envelope) GetVirtualChannelSettlementProposalMsg() *VirtualChannelSettlementProposalMsg { - if x, ok := x.GetMsg().(*Envelope_VirtualChannelSettlementProposalMsg); ok { - return x.VirtualChannelSettlementProposalMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_VirtualChannelSettlementProposalMsg); ok { + return x.VirtualChannelSettlementProposalMsg + } } return nil } func (x *Envelope) GetChannelUpdateAccMsg() *ChannelUpdateAccMsg { - if x, ok := x.GetMsg().(*Envelope_ChannelUpdateAccMsg); ok { - return x.ChannelUpdateAccMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_ChannelUpdateAccMsg); ok { + return x.ChannelUpdateAccMsg + } } return nil } func (x *Envelope) GetChannelUpdateRejMsg() *ChannelUpdateRejMsg { - if x, ok := x.GetMsg().(*Envelope_ChannelUpdateRejMsg); ok { - return x.ChannelUpdateRejMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_ChannelUpdateRejMsg); ok { + return x.ChannelUpdateRejMsg + } } return nil } func (x *Envelope) GetChannelSyncMsg() *ChannelSyncMsg { - if x, ok := x.GetMsg().(*Envelope_ChannelSyncMsg); ok { - return x.ChannelSyncMsg + if x != nil { + if x, ok := x.Msg.(*Envelope_ChannelSyncMsg); ok { + return x.ChannelSyncMsg + } } return nil } @@ -353,20 +384,17 @@ func (*Envelope_ChannelSyncMsg) isEnvelope_Msg() {} // Balance represents the balance of a single asset, for all the channel // participants. type Balance struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Balance [][]byte `protobuf:"bytes,1,rep,name=balance,proto3" json:"balance,omitempty"` unknownFields protoimpl.UnknownFields - - Balance [][]byte `protobuf:"bytes,1,rep,name=balance,proto3" json:"balance,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Balance) Reset() { *x = Balance{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Balance) String() string { @@ -376,8 +404,8 @@ func (x *Balance) String() string { func (*Balance) ProtoMessage() {} func (x *Balance) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[1] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -389,7 +417,7 @@ func (x *Balance) ProtoReflect() protoreflect.Message { // Deprecated: Use Balance.ProtoReflect.Descriptor instead. func (*Balance) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{1} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{1} } func (x *Balance) GetBalance() [][]byte { @@ -402,20 +430,17 @@ func (x *Balance) GetBalance() [][]byte { // Balances represents the balance of all the assets, for all the channel // participants. type Balances struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Balances []*Balance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` unknownFields protoimpl.UnknownFields - - Balances []*Balance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Balances) Reset() { *x = Balances{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Balances) String() string { @@ -425,8 +450,8 @@ func (x *Balances) String() string { func (*Balances) ProtoMessage() {} func (x *Balances) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[2] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -438,7 +463,7 @@ func (x *Balances) ProtoReflect() protoreflect.Message { // Deprecated: Use Balances.ProtoReflect.Descriptor instead. func (*Balances) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{2} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{2} } func (x *Balances) GetBalances() []*Balance { @@ -450,21 +475,18 @@ func (x *Balances) GetBalances() []*Balance { // AddressMapping represents an element of a address mapping. type AddressMapping struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Address []byte `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` unknownFields protoimpl.UnknownFields - - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Address []byte `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AddressMapping) Reset() { *x = AddressMapping{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AddressMapping) String() string { @@ -474,8 +496,8 @@ func (x *AddressMapping) String() string { func (*AddressMapping) ProtoMessage() {} func (x *AddressMapping) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[3] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -487,7 +509,7 @@ func (x *AddressMapping) ProtoReflect() protoreflect.Message { // Deprecated: Use AddressMapping.ProtoReflect.Descriptor instead. func (*AddressMapping) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{3} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{3} } func (x *AddressMapping) GetKey() []byte { @@ -506,20 +528,17 @@ func (x *AddressMapping) GetAddress() []byte { // Address represents the map of addresses for each participant in the channel. type Address struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AddressMapping []*AddressMapping `protobuf:"bytes,1,rep,name=address_mapping,json=addressMapping,proto3" json:"address_mapping,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AddressMapping []*AddressMapping `protobuf:"bytes,1,rep,name=address_mapping,json=addressMapping,proto3" json:"address_mapping,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Address) Reset() { *x = Address{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Address) String() string { @@ -529,8 +548,8 @@ func (x *Address) String() string { func (*Address) ProtoMessage() {} func (x *Address) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[4] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -542,7 +561,7 @@ func (x *Address) ProtoReflect() protoreflect.Message { // Deprecated: Use Address.ProtoReflect.Descriptor instead. func (*Address) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{4} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{4} } func (x *Address) GetAddressMapping() []*AddressMapping { @@ -556,20 +575,17 @@ func (x *Address) GetAddressMapping() []*AddressMapping { // or a virtual channel funding proposal to the corresponding indices in the // parent channel. type IndexMap struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + IndexMap []uint32 `protobuf:"varint,1,rep,packed,name=index_map,json=indexMap,proto3" json:"index_map,omitempty"` unknownFields protoimpl.UnknownFields - - IndexMap []uint32 `protobuf:"varint,1,rep,packed,name=index_map,json=indexMap,proto3" json:"index_map,omitempty"` + sizeCache protoimpl.SizeCache } func (x *IndexMap) Reset() { *x = IndexMap{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *IndexMap) String() string { @@ -579,8 +595,8 @@ func (x *IndexMap) String() string { func (*IndexMap) ProtoMessage() {} func (x *IndexMap) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[5] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -592,7 +608,7 @@ func (x *IndexMap) ProtoReflect() protoreflect.Message { // Deprecated: Use IndexMap.ProtoReflect.Descriptor instead. func (*IndexMap) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{5} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{5} } func (x *IndexMap) GetIndexMap() []uint32 { @@ -604,22 +620,19 @@ func (x *IndexMap) GetIndexMap() []uint32 { // SubAlloc represts a sub allocation. type SubAlloc struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Bals *Balance `protobuf:"bytes,2,opt,name=bals,proto3" json:"bals,omitempty"` + IndexMap *IndexMap `protobuf:"bytes,3,opt,name=index_map,json=indexMap,proto3" json:"index_map,omitempty"` unknownFields protoimpl.UnknownFields - - Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Bals *Balance `protobuf:"bytes,2,opt,name=bals,proto3" json:"bals,omitempty"` - IndexMap *IndexMap `protobuf:"bytes,3,opt,name=index_map,json=indexMap,proto3" json:"index_map,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SubAlloc) Reset() { *x = SubAlloc{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SubAlloc) String() string { @@ -629,8 +642,8 @@ func (x *SubAlloc) String() string { func (*SubAlloc) ProtoMessage() {} func (x *SubAlloc) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[6] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -642,7 +655,7 @@ func (x *SubAlloc) ProtoReflect() protoreflect.Message { // Deprecated: Use SubAlloc.ProtoReflect.Descriptor instead. func (*SubAlloc) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{6} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{6} } func (x *SubAlloc) GetId() []byte { @@ -668,23 +681,20 @@ func (x *SubAlloc) GetIndexMap() *IndexMap { // Allocation represents channel.Allocation. type Allocation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Backends [][]byte `protobuf:"bytes,1,rep,name=backends,proto3" json:"backends,omitempty"` + Assets [][]byte `protobuf:"bytes,2,rep,name=assets,proto3" json:"assets,omitempty"` + Balances *Balances `protobuf:"bytes,3,opt,name=balances,proto3" json:"balances,omitempty"` + Locked []*SubAlloc `protobuf:"bytes,4,rep,name=locked,proto3" json:"locked,omitempty"` unknownFields protoimpl.UnknownFields - - Backends [][]byte `protobuf:"bytes,1,rep,name=backends,proto3" json:"backends,omitempty"` - Assets [][]byte `protobuf:"bytes,2,rep,name=assets,proto3" json:"assets,omitempty"` - Balances *Balances `protobuf:"bytes,3,opt,name=balances,proto3" json:"balances,omitempty"` - Locked []*SubAlloc `protobuf:"bytes,4,rep,name=locked,proto3" json:"locked,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Allocation) Reset() { *x = Allocation{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Allocation) String() string { @@ -694,8 +704,8 @@ func (x *Allocation) String() string { func (*Allocation) ProtoMessage() {} func (x *Allocation) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[7] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -707,7 +717,7 @@ func (x *Allocation) ProtoReflect() protoreflect.Message { // Deprecated: Use Allocation.ProtoReflect.Descriptor instead. func (*Allocation) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{7} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{7} } func (x *Allocation) GetBackends() [][]byte { @@ -740,26 +750,24 @@ func (x *Allocation) GetLocked() []*SubAlloc { // BaseChannelProposal represents client.BaseChannelProposal. type BaseChannelProposal struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ProposalId []byte `protobuf:"bytes,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` - ChallengeDuration uint64 `protobuf:"varint,2,opt,name=challenge_duration,json=challengeDuration,proto3" json:"challenge_duration,omitempty"` - NonceShare []byte `protobuf:"bytes,3,opt,name=nonce_share,json=nonceShare,proto3" json:"nonce_share,omitempty"` - App []byte `protobuf:"bytes,4,opt,name=app,proto3" json:"app,omitempty"` - InitData []byte `protobuf:"bytes,5,opt,name=init_data,json=initData,proto3" json:"init_data,omitempty"` - InitBals *Allocation `protobuf:"bytes,6,opt,name=init_bals,json=initBals,proto3" json:"init_bals,omitempty"` - FundingAgreement *Balances `protobuf:"bytes,7,opt,name=funding_agreement,json=fundingAgreement,proto3" json:"funding_agreement,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ProposalId []byte `protobuf:"bytes,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + ChallengeDuration uint64 `protobuf:"varint,2,opt,name=challenge_duration,json=challengeDuration,proto3" json:"challenge_duration,omitempty"` + NonceShare []byte `protobuf:"bytes,3,opt,name=nonce_share,json=nonceShare,proto3" json:"nonce_share,omitempty"` + App []byte `protobuf:"bytes,4,opt,name=app,proto3" json:"app,omitempty"` + InitData []byte `protobuf:"bytes,5,opt,name=init_data,json=initData,proto3" json:"init_data,omitempty"` + InitBals *Allocation `protobuf:"bytes,6,opt,name=init_bals,json=initBals,proto3" json:"init_bals,omitempty"` + FundingAgreement *Balances `protobuf:"bytes,7,opt,name=funding_agreement,json=fundingAgreement,proto3" json:"funding_agreement,omitempty"` + Aux []byte `protobuf:"bytes,8,opt,name=aux,proto3" json:"aux,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *BaseChannelProposal) Reset() { *x = BaseChannelProposal{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BaseChannelProposal) String() string { @@ -769,8 +777,8 @@ func (x *BaseChannelProposal) String() string { func (*BaseChannelProposal) ProtoMessage() {} func (x *BaseChannelProposal) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[8] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -782,7 +790,7 @@ func (x *BaseChannelProposal) ProtoReflect() protoreflect.Message { // Deprecated: Use BaseChannelProposal.ProtoReflect.Descriptor instead. func (*BaseChannelProposal) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{8} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{8} } func (x *BaseChannelProposal) GetProposalId() []byte { @@ -834,23 +842,27 @@ func (x *BaseChannelProposal) GetFundingAgreement() *Balances { return nil } +func (x *BaseChannelProposal) GetAux() []byte { + if x != nil { + return x.Aux + } + return nil +} + // BaseChannelProposalAcc represents client.BaseChannelProposalAcc. type BaseChannelProposalAcc struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ProposalId []byte `protobuf:"bytes,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + NonceShare []byte `protobuf:"bytes,2,opt,name=nonce_share,json=nonceShare,proto3" json:"nonce_share,omitempty"` unknownFields protoimpl.UnknownFields - - ProposalId []byte `protobuf:"bytes,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` - NonceShare []byte `protobuf:"bytes,2,opt,name=nonce_share,json=nonceShare,proto3" json:"nonce_share,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BaseChannelProposalAcc) Reset() { *x = BaseChannelProposalAcc{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BaseChannelProposalAcc) String() string { @@ -860,8 +872,8 @@ func (x *BaseChannelProposalAcc) String() string { func (*BaseChannelProposalAcc) ProtoMessage() {} func (x *BaseChannelProposalAcc) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[9] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -873,7 +885,7 @@ func (x *BaseChannelProposalAcc) ProtoReflect() protoreflect.Message { // Deprecated: Use BaseChannelProposalAcc.ProtoReflect.Descriptor instead. func (*BaseChannelProposalAcc) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{9} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{9} } func (x *BaseChannelProposalAcc) GetProposalId() []byte { @@ -892,26 +904,24 @@ func (x *BaseChannelProposalAcc) GetNonceShare() []byte { // Params represents channel.Params. type Params struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - ChallengeDuration uint64 `protobuf:"varint,2,opt,name=challenge_duration,json=challengeDuration,proto3" json:"challenge_duration,omitempty"` - Parts []*Address `protobuf:"bytes,3,rep,name=parts,proto3" json:"parts,omitempty"` - App []byte `protobuf:"bytes,4,opt,name=app,proto3" json:"app,omitempty"` - Nonce []byte `protobuf:"bytes,5,opt,name=nonce,proto3" json:"nonce,omitempty"` - LedgerChannel bool `protobuf:"varint,6,opt,name=ledger_channel,json=ledgerChannel,proto3" json:"ledger_channel,omitempty"` - VirtualChannel bool `protobuf:"varint,7,opt,name=virtual_channel,json=virtualChannel,proto3" json:"virtual_channel,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + ChallengeDuration uint64 `protobuf:"varint,2,opt,name=challenge_duration,json=challengeDuration,proto3" json:"challenge_duration,omitempty"` + Parts []*Address `protobuf:"bytes,3,rep,name=parts,proto3" json:"parts,omitempty"` + App []byte `protobuf:"bytes,4,opt,name=app,proto3" json:"app,omitempty"` + Nonce []byte `protobuf:"bytes,5,opt,name=nonce,proto3" json:"nonce,omitempty"` + LedgerChannel bool `protobuf:"varint,6,opt,name=ledger_channel,json=ledgerChannel,proto3" json:"ledger_channel,omitempty"` + VirtualChannel bool `protobuf:"varint,7,opt,name=virtual_channel,json=virtualChannel,proto3" json:"virtual_channel,omitempty"` + Aux []byte `protobuf:"bytes,8,opt,name=aux,proto3" json:"aux,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Params) Reset() { *x = Params{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Params) String() string { @@ -921,8 +931,8 @@ func (x *Params) String() string { func (*Params) ProtoMessage() {} func (x *Params) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[10] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -934,7 +944,7 @@ func (x *Params) ProtoReflect() protoreflect.Message { // Deprecated: Use Params.ProtoReflect.Descriptor instead. func (*Params) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{10} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{10} } func (x *Params) GetId() []byte { @@ -986,27 +996,31 @@ func (x *Params) GetVirtualChannel() bool { return false } +func (x *Params) GetAux() []byte { + if x != nil { + return x.Aux + } + return nil +} + // State represents channel.State. type State struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Version uint64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + App []byte `protobuf:"bytes,3,opt,name=app,proto3" json:"app,omitempty"` + Allocation *Allocation `protobuf:"bytes,4,opt,name=allocation,proto3" json:"allocation,omitempty"` + Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` + IsFinal bool `protobuf:"varint,6,opt,name=is_final,json=isFinal,proto3" json:"is_final,omitempty"` unknownFields protoimpl.UnknownFields - - Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Version uint64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - App []byte `protobuf:"bytes,3,opt,name=app,proto3" json:"app,omitempty"` - Allocation *Allocation `protobuf:"bytes,4,opt,name=allocation,proto3" json:"allocation,omitempty"` - Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` - IsFinal bool `protobuf:"varint,6,opt,name=is_final,json=isFinal,proto3" json:"is_final,omitempty"` + sizeCache protoimpl.SizeCache } func (x *State) Reset() { *x = State{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *State) String() string { @@ -1016,8 +1030,8 @@ func (x *State) String() string { func (*State) ProtoMessage() {} func (x *State) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[11] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1029,7 +1043,7 @@ func (x *State) ProtoReflect() protoreflect.Message { // Deprecated: Use State.ProtoReflect.Descriptor instead. func (*State) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{11} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{11} } func (x *State) GetId() []byte { @@ -1076,21 +1090,18 @@ func (x *State) GetIsFinal() bool { // Transaction represents channel.Transaction. type Transaction struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + State *State `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + Sigs [][]byte `protobuf:"bytes,2,rep,name=sigs,proto3" json:"sigs,omitempty"` unknownFields protoimpl.UnknownFields - - State *State `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` - Sigs [][]byte `protobuf:"bytes,2,rep,name=sigs,proto3" json:"sigs,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Transaction) Reset() { *x = Transaction{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Transaction) String() string { @@ -1100,8 +1111,8 @@ func (x *Transaction) String() string { func (*Transaction) ProtoMessage() {} func (x *Transaction) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[12] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1113,7 +1124,7 @@ func (x *Transaction) ProtoReflect() protoreflect.Message { // Deprecated: Use Transaction.ProtoReflect.Descriptor instead. func (*Transaction) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{12} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{12} } func (x *Transaction) GetState() *State { @@ -1132,22 +1143,19 @@ func (x *Transaction) GetSigs() [][]byte { // SignedState represents channel.SignedState. type SignedState struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` + State *State `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + Sigs [][]byte `protobuf:"bytes,3,rep,name=sigs,proto3" json:"sigs,omitempty"` unknownFields protoimpl.UnknownFields - - Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` - State *State `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` - Sigs [][]byte `protobuf:"bytes,3,rep,name=sigs,proto3" json:"sigs,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SignedState) Reset() { *x = SignedState{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SignedState) String() string { @@ -1157,8 +1165,8 @@ func (x *SignedState) String() string { func (*SignedState) ProtoMessage() {} func (x *SignedState) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[13] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1170,7 +1178,7 @@ func (x *SignedState) ProtoReflect() protoreflect.Message { // Deprecated: Use SignedState.ProtoReflect.Descriptor instead. func (*SignedState) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{13} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{13} } func (x *SignedState) GetParams() *Params { @@ -1196,21 +1204,18 @@ func (x *SignedState) GetSigs() [][]byte { // ChannelUpdate represents channel.ChannelUpdate. type ChannelUpdate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + State *State `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + ActorIdx uint32 `protobuf:"varint,2,opt,name=actor_idx,json=actorIdx,proto3" json:"actor_idx,omitempty"` unknownFields protoimpl.UnknownFields - - State *State `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` - ActorIdx uint32 `protobuf:"varint,2,opt,name=actor_idx,json=actorIdx,proto3" json:"actor_idx,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChannelUpdate) Reset() { *x = ChannelUpdate{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ChannelUpdate) String() string { @@ -1220,8 +1225,8 @@ func (x *ChannelUpdate) String() string { func (*ChannelUpdate) ProtoMessage() {} func (x *ChannelUpdate) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[14] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1233,7 +1238,7 @@ func (x *ChannelUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelUpdate.ProtoReflect.Descriptor instead. func (*ChannelUpdate) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{14} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{14} } func (x *ChannelUpdate) GetState() *State { @@ -1252,20 +1257,17 @@ func (x *ChannelUpdate) GetActorIdx() uint32 { // PingMsg represents wire.PingMsg. type PingMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Created int64 `protobuf:"varint,1,opt,name=created,proto3" json:"created,omitempty"` unknownFields protoimpl.UnknownFields - - Created int64 `protobuf:"varint,1,opt,name=created,proto3" json:"created,omitempty"` + sizeCache protoimpl.SizeCache } func (x *PingMsg) Reset() { *x = PingMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PingMsg) String() string { @@ -1275,8 +1277,8 @@ func (x *PingMsg) String() string { func (*PingMsg) ProtoMessage() {} func (x *PingMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[15] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1288,7 +1290,7 @@ func (x *PingMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use PingMsg.ProtoReflect.Descriptor instead. func (*PingMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{15} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{15} } func (x *PingMsg) GetCreated() int64 { @@ -1300,20 +1302,17 @@ func (x *PingMsg) GetCreated() int64 { // PongMsg represents wire.PongMsg. type PongMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Created int64 `protobuf:"varint,1,opt,name=created,proto3" json:"created,omitempty"` unknownFields protoimpl.UnknownFields - - Created int64 `protobuf:"varint,1,opt,name=created,proto3" json:"created,omitempty"` + sizeCache protoimpl.SizeCache } func (x *PongMsg) Reset() { *x = PongMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PongMsg) String() string { @@ -1323,8 +1322,8 @@ func (x *PongMsg) String() string { func (*PongMsg) ProtoMessage() {} func (x *PongMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[16] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1336,7 +1335,7 @@ func (x *PongMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use PongMsg.ProtoReflect.Descriptor instead. func (*PongMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{16} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{16} } func (x *PongMsg) GetCreated() int64 { @@ -1348,20 +1347,17 @@ func (x *PongMsg) GetCreated() int64 { // ShutdownMsg represents wire.ShutdownMsg. type ShutdownMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"` unknownFields protoimpl.UnknownFields - - Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ShutdownMsg) Reset() { *x = ShutdownMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ShutdownMsg) String() string { @@ -1371,8 +1367,8 @@ func (x *ShutdownMsg) String() string { func (*ShutdownMsg) ProtoMessage() {} func (x *ShutdownMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[17] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1384,7 +1380,7 @@ func (x *ShutdownMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use ShutdownMsg.ProtoReflect.Descriptor instead. func (*ShutdownMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{17} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{17} } func (x *ShutdownMsg) GetReason() string { @@ -1396,20 +1392,17 @@ func (x *ShutdownMsg) GetReason() string { // AuthResponseMsg represents wire.AuthResponseMsg. type AuthResponseMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` unknownFields protoimpl.UnknownFields - - Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AuthResponseMsg) Reset() { *x = AuthResponseMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AuthResponseMsg) String() string { @@ -1419,8 +1412,8 @@ func (x *AuthResponseMsg) String() string { func (*AuthResponseMsg) ProtoMessage() {} func (x *AuthResponseMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[18] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1432,7 +1425,7 @@ func (x *AuthResponseMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthResponseMsg.ProtoReflect.Descriptor instead. func (*AuthResponseMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{18} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{18} } func (x *AuthResponseMsg) GetSignature() []byte { @@ -1444,22 +1437,19 @@ func (x *AuthResponseMsg) GetSignature() []byte { // LedgerChannelProposalMsg represents client.LedgerChannelProposalMsg. type LedgerChannelProposalMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BaseChannelProposal *BaseChannelProposal `protobuf:"bytes,1,opt,name=base_channel_proposal,json=baseChannelProposal,proto3" json:"base_channel_proposal,omitempty"` - Participant *Address `protobuf:"bytes,2,opt,name=participant,proto3" json:"participant,omitempty"` - Peers []*Address `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + BaseChannelProposal *BaseChannelProposal `protobuf:"bytes,1,opt,name=base_channel_proposal,json=baseChannelProposal,proto3" json:"base_channel_proposal,omitempty"` + Participant *Address `protobuf:"bytes,2,opt,name=participant,proto3" json:"participant,omitempty"` + Peers []*Address `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LedgerChannelProposalMsg) Reset() { *x = LedgerChannelProposalMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *LedgerChannelProposalMsg) String() string { @@ -1469,8 +1459,8 @@ func (x *LedgerChannelProposalMsg) String() string { func (*LedgerChannelProposalMsg) ProtoMessage() {} func (x *LedgerChannelProposalMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[19] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1482,7 +1472,7 @@ func (x *LedgerChannelProposalMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use LedgerChannelProposalMsg.ProtoReflect.Descriptor instead. func (*LedgerChannelProposalMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{19} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{19} } func (x *LedgerChannelProposalMsg) GetBaseChannelProposal() *BaseChannelProposal { @@ -1508,21 +1498,18 @@ func (x *LedgerChannelProposalMsg) GetPeers() []*Address { // LedgerChannelProposalAccMsg represents client.LedgerChannelProposalAccMsg. type LedgerChannelProposalAccMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` BaseChannelProposalAcc *BaseChannelProposalAcc `protobuf:"bytes,1,opt,name=base_channel_proposal_acc,json=baseChannelProposalAcc,proto3" json:"base_channel_proposal_acc,omitempty"` Participant *Address `protobuf:"bytes,2,opt,name=participant,proto3" json:"participant,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LedgerChannelProposalAccMsg) Reset() { *x = LedgerChannelProposalAccMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *LedgerChannelProposalAccMsg) String() string { @@ -1532,8 +1519,8 @@ func (x *LedgerChannelProposalAccMsg) String() string { func (*LedgerChannelProposalAccMsg) ProtoMessage() {} func (x *LedgerChannelProposalAccMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[20] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1545,7 +1532,7 @@ func (x *LedgerChannelProposalAccMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use LedgerChannelProposalAccMsg.ProtoReflect.Descriptor instead. func (*LedgerChannelProposalAccMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{20} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{20} } func (x *LedgerChannelProposalAccMsg) GetBaseChannelProposalAcc() *BaseChannelProposalAcc { @@ -1564,21 +1551,18 @@ func (x *LedgerChannelProposalAccMsg) GetParticipant() *Address { // SubChannelProposalMsg represents client.SubChannelProposalMsg. type SubChannelProposalMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BaseChannelProposal *BaseChannelProposal `protobuf:"bytes,1,opt,name=base_channel_proposal,json=baseChannelProposal,proto3" json:"base_channel_proposal,omitempty"` - Parent []byte `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + BaseChannelProposal *BaseChannelProposal `protobuf:"bytes,1,opt,name=base_channel_proposal,json=baseChannelProposal,proto3" json:"base_channel_proposal,omitempty"` + Parent []byte `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SubChannelProposalMsg) Reset() { *x = SubChannelProposalMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SubChannelProposalMsg) String() string { @@ -1588,8 +1572,8 @@ func (x *SubChannelProposalMsg) String() string { func (*SubChannelProposalMsg) ProtoMessage() {} func (x *SubChannelProposalMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[21] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1601,7 +1585,7 @@ func (x *SubChannelProposalMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use SubChannelProposalMsg.ProtoReflect.Descriptor instead. func (*SubChannelProposalMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{21} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{21} } func (x *SubChannelProposalMsg) GetBaseChannelProposal() *BaseChannelProposal { @@ -1620,20 +1604,17 @@ func (x *SubChannelProposalMsg) GetParent() []byte { // SubChannelProposalAccMsg represents client.SubChannelProposalAccMsg. type SubChannelProposalAccMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` BaseChannelProposalAcc *BaseChannelProposalAcc `protobuf:"bytes,1,opt,name=base_channel_proposal_acc,json=baseChannelProposalAcc,proto3" json:"base_channel_proposal_acc,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SubChannelProposalAccMsg) Reset() { *x = SubChannelProposalAccMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SubChannelProposalAccMsg) String() string { @@ -1643,8 +1624,8 @@ func (x *SubChannelProposalAccMsg) String() string { func (*SubChannelProposalAccMsg) ProtoMessage() {} func (x *SubChannelProposalAccMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[22] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1656,7 +1637,7 @@ func (x *SubChannelProposalAccMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use SubChannelProposalAccMsg.ProtoReflect.Descriptor instead. func (*SubChannelProposalAccMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{22} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{22} } func (x *SubChannelProposalAccMsg) GetBaseChannelProposalAcc() *BaseChannelProposalAcc { @@ -1668,24 +1649,21 @@ func (x *SubChannelProposalAccMsg) GetBaseChannelProposalAcc() *BaseChannelPropo // VirtualChannelProposalMsg represents client.VirtualChannelProposalMsg. type VirtualChannelProposalMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BaseChannelProposal *BaseChannelProposal `protobuf:"bytes,1,opt,name=base_channel_proposal,json=baseChannelProposal,proto3" json:"base_channel_proposal,omitempty"` - Proposer *Address `protobuf:"bytes,2,opt,name=proposer,proto3" json:"proposer,omitempty"` - Peers []*Address `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` - Parents [][]byte `protobuf:"bytes,4,rep,name=parents,proto3" json:"parents,omitempty"` - IndexMaps []*IndexMap `protobuf:"bytes,5,rep,name=index_maps,json=indexMaps,proto3" json:"index_maps,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + BaseChannelProposal *BaseChannelProposal `protobuf:"bytes,1,opt,name=base_channel_proposal,json=baseChannelProposal,proto3" json:"base_channel_proposal,omitempty"` + Proposer *Address `protobuf:"bytes,2,opt,name=proposer,proto3" json:"proposer,omitempty"` + Peers []*Address `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` + Parents [][]byte `protobuf:"bytes,4,rep,name=parents,proto3" json:"parents,omitempty"` + IndexMaps []*IndexMap `protobuf:"bytes,5,rep,name=index_maps,json=indexMaps,proto3" json:"index_maps,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VirtualChannelProposalMsg) Reset() { *x = VirtualChannelProposalMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *VirtualChannelProposalMsg) String() string { @@ -1695,8 +1673,8 @@ func (x *VirtualChannelProposalMsg) String() string { func (*VirtualChannelProposalMsg) ProtoMessage() {} func (x *VirtualChannelProposalMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[23] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1708,7 +1686,7 @@ func (x *VirtualChannelProposalMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use VirtualChannelProposalMsg.ProtoReflect.Descriptor instead. func (*VirtualChannelProposalMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{23} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{23} } func (x *VirtualChannelProposalMsg) GetBaseChannelProposal() *BaseChannelProposal { @@ -1748,21 +1726,18 @@ func (x *VirtualChannelProposalMsg) GetIndexMaps() []*IndexMap { // VirtualChannelProposalAccMsg represents client.VirtualChannelProposalAccMsg. type VirtualChannelProposalAccMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` BaseChannelProposalAcc *BaseChannelProposalAcc `protobuf:"bytes,1,opt,name=base_channel_proposal_acc,json=baseChannelProposalAcc,proto3" json:"base_channel_proposal_acc,omitempty"` Responder *Address `protobuf:"bytes,2,opt,name=responder,proto3" json:"responder,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VirtualChannelProposalAccMsg) Reset() { *x = VirtualChannelProposalAccMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *VirtualChannelProposalAccMsg) String() string { @@ -1772,8 +1747,8 @@ func (x *VirtualChannelProposalAccMsg) String() string { func (*VirtualChannelProposalAccMsg) ProtoMessage() {} func (x *VirtualChannelProposalAccMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[24] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1785,7 +1760,7 @@ func (x *VirtualChannelProposalAccMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use VirtualChannelProposalAccMsg.ProtoReflect.Descriptor instead. func (*VirtualChannelProposalAccMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{24} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{24} } func (x *VirtualChannelProposalAccMsg) GetBaseChannelProposalAcc() *BaseChannelProposalAcc { @@ -1804,21 +1779,18 @@ func (x *VirtualChannelProposalAccMsg) GetResponder() *Address { // ChannelProposalRejMsg represents client.ChannelProposalRejMsg. type ChannelProposalRejMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ProposalId []byte `protobuf:"bytes,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` unknownFields protoimpl.UnknownFields - - ProposalId []byte `protobuf:"bytes,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChannelProposalRejMsg) Reset() { *x = ChannelProposalRejMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ChannelProposalRejMsg) String() string { @@ -1828,8 +1800,8 @@ func (x *ChannelProposalRejMsg) String() string { func (*ChannelProposalRejMsg) ProtoMessage() {} func (x *ChannelProposalRejMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[25] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1841,7 +1813,7 @@ func (x *ChannelProposalRejMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelProposalRejMsg.ProtoReflect.Descriptor instead. func (*ChannelProposalRejMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{25} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{25} } func (x *ChannelProposalRejMsg) GetProposalId() []byte { @@ -1860,21 +1832,18 @@ func (x *ChannelProposalRejMsg) GetReason() string { // ChannelUpdateMsg represents client.ChannelUpdateMsg. type ChannelUpdateMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ChannelUpdate *ChannelUpdate `protobuf:"bytes,1,opt,name=channel_update,json=channelUpdate,proto3" json:"channel_update,omitempty"` + Sig []byte `protobuf:"bytes,2,opt,name=sig,proto3" json:"sig,omitempty"` unknownFields protoimpl.UnknownFields - - ChannelUpdate *ChannelUpdate `protobuf:"bytes,1,opt,name=channel_update,json=channelUpdate,proto3" json:"channel_update,omitempty"` - Sig []byte `protobuf:"bytes,2,opt,name=sig,proto3" json:"sig,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChannelUpdateMsg) Reset() { *x = ChannelUpdateMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ChannelUpdateMsg) String() string { @@ -1884,8 +1853,8 @@ func (x *ChannelUpdateMsg) String() string { func (*ChannelUpdateMsg) ProtoMessage() {} func (x *ChannelUpdateMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[26] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1897,7 +1866,7 @@ func (x *ChannelUpdateMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelUpdateMsg.ProtoReflect.Descriptor instead. func (*ChannelUpdateMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{26} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{26} } func (x *ChannelUpdateMsg) GetChannelUpdate() *ChannelUpdate { @@ -1917,22 +1886,19 @@ func (x *ChannelUpdateMsg) GetSig() []byte { // VirtualChannelFundingProposalMsg represents // client.VirtualChannelFundingProposalMsg. type VirtualChannelFundingProposalMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ChannelUpdateMsg *ChannelUpdateMsg `protobuf:"bytes,1,opt,name=channel_update_msg,json=channelUpdateMsg,proto3" json:"channel_update_msg,omitempty"` - Initial *SignedState `protobuf:"bytes,2,opt,name=initial,proto3" json:"initial,omitempty"` - IndexMap *IndexMap `protobuf:"bytes,3,opt,name=index_map,json=indexMap,proto3" json:"index_map,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ChannelUpdateMsg *ChannelUpdateMsg `protobuf:"bytes,1,opt,name=channel_update_msg,json=channelUpdateMsg,proto3" json:"channel_update_msg,omitempty"` + Initial *SignedState `protobuf:"bytes,2,opt,name=initial,proto3" json:"initial,omitempty"` + IndexMap *IndexMap `protobuf:"bytes,3,opt,name=index_map,json=indexMap,proto3" json:"index_map,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VirtualChannelFundingProposalMsg) Reset() { *x = VirtualChannelFundingProposalMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *VirtualChannelFundingProposalMsg) String() string { @@ -1942,8 +1908,8 @@ func (x *VirtualChannelFundingProposalMsg) String() string { func (*VirtualChannelFundingProposalMsg) ProtoMessage() {} func (x *VirtualChannelFundingProposalMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[27] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1955,7 +1921,7 @@ func (x *VirtualChannelFundingProposalMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use VirtualChannelFundingProposalMsg.ProtoReflect.Descriptor instead. func (*VirtualChannelFundingProposalMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{27} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{27} } func (x *VirtualChannelFundingProposalMsg) GetChannelUpdateMsg() *ChannelUpdateMsg { @@ -1982,21 +1948,18 @@ func (x *VirtualChannelFundingProposalMsg) GetIndexMap() *IndexMap { // VirtualChannelSettlementProposalMsg represents // client.VirtualChannelSettlementProposalMsg. type VirtualChannelSettlementProposalMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ChannelUpdateMsg *ChannelUpdateMsg `protobuf:"bytes,1,opt,name=channel_update_msg,json=channelUpdateMsg,proto3" json:"channel_update_msg,omitempty"` - Final *SignedState `protobuf:"bytes,2,opt,name=final,proto3" json:"final,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ChannelUpdateMsg *ChannelUpdateMsg `protobuf:"bytes,1,opt,name=channel_update_msg,json=channelUpdateMsg,proto3" json:"channel_update_msg,omitempty"` + Final *SignedState `protobuf:"bytes,2,opt,name=final,proto3" json:"final,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VirtualChannelSettlementProposalMsg) Reset() { *x = VirtualChannelSettlementProposalMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *VirtualChannelSettlementProposalMsg) String() string { @@ -2006,8 +1969,8 @@ func (x *VirtualChannelSettlementProposalMsg) String() string { func (*VirtualChannelSettlementProposalMsg) ProtoMessage() {} func (x *VirtualChannelSettlementProposalMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[28] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2019,7 +1982,7 @@ func (x *VirtualChannelSettlementProposalMsg) ProtoReflect() protoreflect.Messag // Deprecated: Use VirtualChannelSettlementProposalMsg.ProtoReflect.Descriptor instead. func (*VirtualChannelSettlementProposalMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{28} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{28} } func (x *VirtualChannelSettlementProposalMsg) GetChannelUpdateMsg() *ChannelUpdateMsg { @@ -2038,22 +2001,19 @@ func (x *VirtualChannelSettlementProposalMsg) GetFinal() *SignedState { // ChannelUpdateAccMsg represents client.ChannelUpdateAccMsg. type ChannelUpdateAccMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ChannelId []byte `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` + Version uint64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + Sig []byte `protobuf:"bytes,3,opt,name=sig,proto3" json:"sig,omitempty"` unknownFields protoimpl.UnknownFields - - ChannelId []byte `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - Version uint64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - Sig []byte `protobuf:"bytes,3,opt,name=sig,proto3" json:"sig,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChannelUpdateAccMsg) Reset() { *x = ChannelUpdateAccMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ChannelUpdateAccMsg) String() string { @@ -2063,8 +2023,8 @@ func (x *ChannelUpdateAccMsg) String() string { func (*ChannelUpdateAccMsg) ProtoMessage() {} func (x *ChannelUpdateAccMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[29] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2076,7 +2036,7 @@ func (x *ChannelUpdateAccMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelUpdateAccMsg.ProtoReflect.Descriptor instead. func (*ChannelUpdateAccMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{29} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{29} } func (x *ChannelUpdateAccMsg) GetChannelId() []byte { @@ -2102,22 +2062,19 @@ func (x *ChannelUpdateAccMsg) GetSig() []byte { // ChannelUpdateRejMsg represents client.ChannelUpdateRejMsg. type ChannelUpdateRejMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ChannelId []byte `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` + Version uint64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` unknownFields protoimpl.UnknownFields - - ChannelId []byte `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - Version uint64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChannelUpdateRejMsg) Reset() { *x = ChannelUpdateRejMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ChannelUpdateRejMsg) String() string { @@ -2127,8 +2084,8 @@ func (x *ChannelUpdateRejMsg) String() string { func (*ChannelUpdateRejMsg) ProtoMessage() {} func (x *ChannelUpdateRejMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[30] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2140,7 +2097,7 @@ func (x *ChannelUpdateRejMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelUpdateRejMsg.ProtoReflect.Descriptor instead. func (*ChannelUpdateRejMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{30} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{30} } func (x *ChannelUpdateRejMsg) GetChannelId() []byte { @@ -2166,21 +2123,18 @@ func (x *ChannelUpdateRejMsg) GetReason() string { // ChannelSyncMsg represents client.ChannelSyncMsg. type ChannelSyncMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Phase uint32 `protobuf:"varint,1,opt,name=phase,proto3" json:"phase,omitempty"` + CurrentTx *Transaction `protobuf:"bytes,2,opt,name=current_tx,json=currentTx,proto3" json:"current_tx,omitempty"` unknownFields protoimpl.UnknownFields - - Phase uint32 `protobuf:"varint,1,opt,name=phase,proto3" json:"phase,omitempty"` - CurrentTx *Transaction `protobuf:"bytes,2,opt,name=current_tx,json=currentTx,proto3" json:"current_tx,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChannelSyncMsg) Reset() { *x = ChannelSyncMsg{} - if protoimpl.UnsafeEnabled { - mi := &file_wire_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_wire_protobuf_wire_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ChannelSyncMsg) String() string { @@ -2190,8 +2144,8 @@ func (x *ChannelSyncMsg) String() string { func (*ChannelSyncMsg) ProtoMessage() {} func (x *ChannelSyncMsg) ProtoReflect() protoreflect.Message { - mi := &file_wire_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_wire_protobuf_wire_proto_msgTypes[31] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2203,7 +2157,7 @@ func (x *ChannelSyncMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelSyncMsg.ProtoReflect.Descriptor instead. func (*ChannelSyncMsg) Descriptor() ([]byte, []int) { - return file_wire_proto_rawDescGZIP(), []int{31} + return file_wire_protobuf_wire_proto_rawDescGZIP(), []int{31} } func (x *ChannelSyncMsg) GetPhase() uint32 { @@ -2220,368 +2174,171 @@ func (x *ChannelSyncMsg) GetCurrentTx() *Transaction { return nil } -var File_wire_proto protoreflect.FileDescriptor - -var file_wire_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x70, 0x65, - 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x22, 0xf5, 0x0c, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x65, - 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x12, 0x30, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x07, 0x70, 0x69, 0x6e, 0x67, - 0x4d, 0x73, 0x67, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x6f, 0x6e, 0x67, 0x5f, 0x6d, 0x73, 0x67, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, - 0x65, 0x2e, 0x50, 0x6f, 0x6e, 0x67, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x07, 0x70, 0x6f, 0x6e, - 0x67, 0x4d, 0x73, 0x67, 0x12, 0x3b, 0x0a, 0x0c, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, - 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x65, 0x72, - 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4d, - 0x73, 0x67, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x73, - 0x67, 0x12, 0x48, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, - 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x64, 0x0a, 0x1b, 0x6c, - 0x65, 0x64, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4c, 0x65, 0x64, - 0x67, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x18, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, - 0x67, 0x12, 0x6e, 0x0a, 0x1f, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, - 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, - 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, - 0x73, 0x67, 0x48, 0x00, 0x52, 0x1b, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, 0x73, - 0x67, 0x12, 0x5b, 0x0a, 0x18, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x53, 0x75, 0x62, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x15, 0x73, 0x75, 0x62, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x65, - 0x0a, 0x1c, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x53, 0x75, 0x62, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x18, 0x73, 0x75, 0x62, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, - 0x63, 0x63, 0x4d, 0x73, 0x67, 0x12, 0x67, 0x0a, 0x1c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, - 0x6c, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, - 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, - 0x67, 0x48, 0x00, 0x52, 0x19, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x71, - 0x0a, 0x20, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x5f, 0x6d, - 0x73, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, - 0x77, 0x69, 0x72, 0x65, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, 0x73, - 0x67, 0x48, 0x00, 0x52, 0x1c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, 0x73, - 0x67, 0x12, 0x5b, 0x0a, 0x18, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x6a, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, - 0x65, 0x6a, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x15, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x6a, 0x4d, 0x73, 0x67, 0x12, 0x4b, - 0x0a, 0x12, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x65, 0x72, - 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x10, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x7d, 0x0a, 0x24, 0x76, - 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, - 0x6d, 0x73, 0x67, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x75, - 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x20, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, - 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x86, 0x01, 0x0a, 0x27, 0x76, - 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x73, - 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, - 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x23, - 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, - 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x4d, 0x73, 0x67, 0x12, 0x55, 0x0a, 0x16, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x11, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, - 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x13, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x4d, 0x73, 0x67, 0x12, 0x55, 0x0a, 0x16, 0x63, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x6a, - 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, - 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x6a, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x13, 0x63, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x6a, 0x4d, 0x73, - 0x67, 0x12, 0x45, 0x0a, 0x10, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x73, 0x79, 0x6e, - 0x63, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x65, - 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, - 0x79, 0x6e, 0x63, 0x4d, 0x73, 0x67, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x73, 0x67, 0x42, 0x05, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x22, - 0x23, 0x0a, 0x07, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x62, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x0a, 0x08, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x12, 0x2e, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x22, 0x3c, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x4d, - 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x42, 0x0a, 0x0f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x22, 0x27, 0x0a, - 0x08, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x22, 0x74, 0x0a, 0x08, 0x53, 0x75, 0x62, 0x41, 0x6c, 0x6c, - 0x6f, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x26, 0x0a, 0x04, 0x62, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x52, 0x04, 0x62, 0x61, 0x6c, 0x73, 0x12, 0x30, 0x0a, 0x09, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, - 0x61, 0x70, 0x52, 0x08, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x22, 0x9e, 0x01, 0x0a, - 0x0a, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, - 0x2f, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x12, 0x2b, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, 0x75, 0x62, - 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x22, 0xab, 0x02, - 0x0a, 0x13, 0x42, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, - 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, - 0x6e, 0x67, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x11, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x5f, 0x73, - 0x68, 0x61, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6e, 0x6f, 0x6e, 0x63, - 0x65, 0x53, 0x68, 0x61, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 0x70, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x03, 0x61, 0x70, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x69, 0x74, - 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x69, 0x6e, 0x69, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x32, 0x0a, 0x09, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x62, 0x61, - 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, - 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x08, 0x69, 0x6e, 0x69, 0x74, 0x42, 0x61, 0x6c, 0x73, 0x12, 0x40, 0x0a, 0x11, 0x66, 0x75, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x10, 0x66, 0x75, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x41, 0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x5a, 0x0a, 0x16, 0x42, - 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x41, 0x63, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, - 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x5f, - 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6e, 0x6f, 0x6e, - 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x65, 0x22, 0xe9, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, - 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, - 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x61, - 0x70, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x61, 0x70, 0x70, 0x12, 0x14, 0x0a, - 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6e, 0x6f, - 0x6e, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6c, 0x65, 0x64, - 0x67, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x69, - 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0e, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x22, 0xa9, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 0x70, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x61, 0x70, 0x70, 0x12, 0x35, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x22, - 0x49, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x69, 0x67, 0x73, 0x22, 0x74, 0x0a, 0x0b, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x65, 0x72, 0x75, - 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x73, 0x69, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x69, 0x67, 0x73, - 0x22, 0x54, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x63, 0x74, - 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x63, - 0x74, 0x6f, 0x72, 0x49, 0x64, 0x78, 0x22, 0x23, 0x0a, 0x07, 0x50, 0x69, 0x6e, 0x67, 0x4d, 0x73, - 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x23, 0x0a, 0x07, 0x50, - 0x6f, 0x6e, 0x67, 0x4d, 0x73, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x22, 0x25, 0x0a, 0x0b, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x73, 0x67, 0x12, - 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x0f, 0x41, 0x75, 0x74, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xce, 0x01, 0x0a, 0x18, 0x4c, 0x65, 0x64, - 0x67, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x52, 0x0a, 0x15, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x42, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x13, 0x62, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x0b, 0x70, 0x61, 0x72, - 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x12, - 0x28, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x1b, 0x4c, 0x65, - 0x64, 0x67, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, 0x73, 0x67, 0x12, 0x5c, 0x0a, 0x19, 0x62, 0x61, 0x73, - 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, - 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x52, - 0x16, 0x62, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x12, 0x34, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, - 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x22, 0x83, 0x01, - 0x0a, 0x15, 0x53, 0x75, 0x62, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x52, 0x0a, 0x15, 0x62, 0x61, 0x73, 0x65, 0x5f, - 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x13, 0x62, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x22, 0x78, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, 0x73, 0x67, 0x12, - 0x5c, 0x0a, 0x19, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, - 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x41, 0x63, 0x63, 0x52, 0x16, 0x62, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x22, 0x97, 0x02, - 0x0a, 0x19, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x52, 0x0a, 0x15, 0x62, - 0x61, 0x73, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, - 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x13, 0x62, 0x61, 0x73, 0x65, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, - 0x2e, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x12, - 0x28, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x0a, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x70, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, - 0x69, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x52, 0x09, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x73, 0x22, 0xae, 0x01, 0x0a, 0x1c, 0x56, 0x69, 0x72, 0x74, - 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x41, 0x63, 0x63, 0x4d, 0x73, 0x67, 0x12, 0x5c, 0x0a, 0x19, 0x62, 0x61, 0x73, 0x65, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, - 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, - 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x52, 0x16, - 0x62, 0x61, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x12, 0x30, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x65, 0x72, 0x75, - 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x22, 0x50, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x6a, 0x4d, 0x73, - 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x65, 0x0a, 0x10, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x3f, - 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x10, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, - 0x67, 0x22, 0xd1, 0x01, 0x0a, 0x20, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x49, 0x0a, 0x12, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x52, - 0x10, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x73, - 0x67, 0x12, 0x30, 0x0a, 0x07, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x61, 0x6c, 0x12, 0x30, 0x0a, 0x09, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x70, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x52, 0x08, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x4d, 0x61, 0x70, 0x22, 0x9e, 0x01, 0x0a, 0x23, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, - 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x49, 0x0a, - 0x12, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, - 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x65, 0x72, 0x75, - 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x52, 0x10, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x77, - 0x69, 0x72, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x05, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x60, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x4d, 0x73, 0x67, 0x12, 0x1d, 0x0a, - 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x22, 0x66, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x6a, 0x4d, 0x73, 0x67, 0x12, - 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x18, - 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x22, 0x5d, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x4d, - 0x73, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x0a, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, - 0x65, 0x72, 0x75, 0x6e, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x78, 0x42, - 0x26, 0x5a, 0x24, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x2f, 0x67, 0x6f, 0x2d, 0x70, 0x65, 0x72, 0x75, 0x6e, 0x2f, 0x77, 0x69, 0x72, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +var File_wire_protobuf_wire_proto protoreflect.FileDescriptor + +const file_wire_protobuf_wire_proto_rawDesc = "" + + "\n" + + "\x18wire/protobuf/wire.proto\x12\tperunwire\"\xf5\f\n" + + "\bEnvelope\x12*\n" + + "\x06sender\x18\x01 \x01(\v2\x12.perunwire.AddressR\x06sender\x120\n" + + "\trecipient\x18\x02 \x01(\v2\x12.perunwire.AddressR\trecipient\x12/\n" + + "\bping_msg\x18\x03 \x01(\v2\x12.perunwire.PingMsgH\x00R\apingMsg\x12/\n" + + "\bpong_msg\x18\x04 \x01(\v2\x12.perunwire.PongMsgH\x00R\apongMsg\x12;\n" + + "\fshutdown_msg\x18\x05 \x01(\v2\x16.perunwire.ShutdownMsgH\x00R\vshutdownMsg\x12H\n" + + "\x11auth_response_msg\x18\x06 \x01(\v2\x1a.perunwire.AuthResponseMsgH\x00R\x0fauthResponseMsg\x12d\n" + + "\x1bledger_channel_proposal_msg\x18\a \x01(\v2#.perunwire.LedgerChannelProposalMsgH\x00R\x18ledgerChannelProposalMsg\x12n\n" + + "\x1fledger_channel_proposal_acc_msg\x18\b \x01(\v2&.perunwire.LedgerChannelProposalAccMsgH\x00R\x1bledgerChannelProposalAccMsg\x12[\n" + + "\x18sub_channel_proposal_msg\x18\t \x01(\v2 .perunwire.SubChannelProposalMsgH\x00R\x15subChannelProposalMsg\x12e\n" + + "\x1csub_channel_proposal_acc_msg\x18\n" + + " \x01(\v2#.perunwire.SubChannelProposalAccMsgH\x00R\x18subChannelProposalAccMsg\x12g\n" + + "\x1cvirtual_channel_proposal_msg\x18\v \x01(\v2$.perunwire.VirtualChannelProposalMsgH\x00R\x19virtualChannelProposalMsg\x12q\n" + + " virtual_channel_proposal_acc_msg\x18\f \x01(\v2'.perunwire.VirtualChannelProposalAccMsgH\x00R\x1cvirtualChannelProposalAccMsg\x12[\n" + + "\x18channel_proposal_rej_msg\x18\r \x01(\v2 .perunwire.ChannelProposalRejMsgH\x00R\x15channelProposalRejMsg\x12K\n" + + "\x12channel_update_msg\x18\x0e \x01(\v2\x1b.perunwire.ChannelUpdateMsgH\x00R\x10channelUpdateMsg\x12}\n" + + "$virtual_channel_funding_proposal_msg\x18\x0f \x01(\v2+.perunwire.VirtualChannelFundingProposalMsgH\x00R virtualChannelFundingProposalMsg\x12\x86\x01\n" + + "'virtual_channel_settlement_proposal_msg\x18\x10 \x01(\v2..perunwire.VirtualChannelSettlementProposalMsgH\x00R#virtualChannelSettlementProposalMsg\x12U\n" + + "\x16channel_update_acc_msg\x18\x11 \x01(\v2\x1e.perunwire.ChannelUpdateAccMsgH\x00R\x13channelUpdateAccMsg\x12U\n" + + "\x16channel_update_rej_msg\x18\x12 \x01(\v2\x1e.perunwire.ChannelUpdateRejMsgH\x00R\x13channelUpdateRejMsg\x12E\n" + + "\x10channel_sync_msg\x18\x13 \x01(\v2\x19.perunwire.ChannelSyncMsgH\x00R\x0echannelSyncMsgB\x05\n" + + "\x03msg\"#\n" + + "\aBalance\x12\x18\n" + + "\abalance\x18\x01 \x03(\fR\abalance\":\n" + + "\bBalances\x12.\n" + + "\bbalances\x18\x01 \x03(\v2\x12.perunwire.BalanceR\bbalances\"<\n" + + "\x0eAddressMapping\x12\x10\n" + + "\x03key\x18\x01 \x01(\fR\x03key\x12\x18\n" + + "\aaddress\x18\x02 \x01(\fR\aaddress\"M\n" + + "\aAddress\x12B\n" + + "\x0faddress_mapping\x18\x01 \x03(\v2\x19.perunwire.AddressMappingR\x0eaddressMapping\"'\n" + + "\bIndexMap\x12\x1b\n" + + "\tindex_map\x18\x01 \x03(\rR\bindexMap\"t\n" + + "\bSubAlloc\x12\x0e\n" + + "\x02id\x18\x01 \x01(\fR\x02id\x12&\n" + + "\x04bals\x18\x02 \x01(\v2\x12.perunwire.BalanceR\x04bals\x120\n" + + "\tindex_map\x18\x03 \x01(\v2\x13.perunwire.IndexMapR\bindexMap\"\x9e\x01\n" + + "\n" + + "Allocation\x12\x1a\n" + + "\bbackends\x18\x01 \x03(\fR\bbackends\x12\x16\n" + + "\x06assets\x18\x02 \x03(\fR\x06assets\x12/\n" + + "\bbalances\x18\x03 \x01(\v2\x13.perunwire.BalancesR\bbalances\x12+\n" + + "\x06locked\x18\x04 \x03(\v2\x13.perunwire.SubAllocR\x06locked\"\xbd\x02\n" + + "\x13BaseChannelProposal\x12\x1f\n" + + "\vproposal_id\x18\x01 \x01(\fR\n" + + "proposalId\x12-\n" + + "\x12challenge_duration\x18\x02 \x01(\x04R\x11challengeDuration\x12\x1f\n" + + "\vnonce_share\x18\x03 \x01(\fR\n" + + "nonceShare\x12\x10\n" + + "\x03app\x18\x04 \x01(\fR\x03app\x12\x1b\n" + + "\tinit_data\x18\x05 \x01(\fR\binitData\x122\n" + + "\tinit_bals\x18\x06 \x01(\v2\x15.perunwire.AllocationR\binitBals\x12@\n" + + "\x11funding_agreement\x18\a \x01(\v2\x13.perunwire.BalancesR\x10fundingAgreement\x12\x10\n" + + "\x03aux\x18\b \x01(\fR\x03aux\"Z\n" + + "\x16BaseChannelProposalAcc\x12\x1f\n" + + "\vproposal_id\x18\x01 \x01(\fR\n" + + "proposalId\x12\x1f\n" + + "\vnonce_share\x18\x02 \x01(\fR\n" + + "nonceShare\"\xfb\x01\n" + + "\x06Params\x12\x0e\n" + + "\x02id\x18\x01 \x01(\fR\x02id\x12-\n" + + "\x12challenge_duration\x18\x02 \x01(\x04R\x11challengeDuration\x12(\n" + + "\x05parts\x18\x03 \x03(\v2\x12.perunwire.AddressR\x05parts\x12\x10\n" + + "\x03app\x18\x04 \x01(\fR\x03app\x12\x14\n" + + "\x05nonce\x18\x05 \x01(\fR\x05nonce\x12%\n" + + "\x0eledger_channel\x18\x06 \x01(\bR\rledgerChannel\x12'\n" + + "\x0fvirtual_channel\x18\a \x01(\bR\x0evirtualChannel\x12\x10\n" + + "\x03aux\x18\b \x01(\fR\x03aux\"\xa9\x01\n" + + "\x05State\x12\x0e\n" + + "\x02id\x18\x01 \x01(\fR\x02id\x12\x18\n" + + "\aversion\x18\x02 \x01(\x04R\aversion\x12\x10\n" + + "\x03app\x18\x03 \x01(\fR\x03app\x125\n" + + "\n" + + "allocation\x18\x04 \x01(\v2\x15.perunwire.AllocationR\n" + + "allocation\x12\x12\n" + + "\x04data\x18\x05 \x01(\fR\x04data\x12\x19\n" + + "\bis_final\x18\x06 \x01(\bR\aisFinal\"I\n" + + "\vTransaction\x12&\n" + + "\x05state\x18\x01 \x01(\v2\x10.perunwire.StateR\x05state\x12\x12\n" + + "\x04sigs\x18\x02 \x03(\fR\x04sigs\"t\n" + + "\vSignedState\x12)\n" + + "\x06params\x18\x01 \x01(\v2\x11.perunwire.ParamsR\x06params\x12&\n" + + "\x05state\x18\x02 \x01(\v2\x10.perunwire.StateR\x05state\x12\x12\n" + + "\x04sigs\x18\x03 \x03(\fR\x04sigs\"T\n" + + "\rChannelUpdate\x12&\n" + + "\x05state\x18\x01 \x01(\v2\x10.perunwire.StateR\x05state\x12\x1b\n" + + "\tactor_idx\x18\x02 \x01(\rR\bactorIdx\"#\n" + + "\aPingMsg\x12\x18\n" + + "\acreated\x18\x01 \x01(\x03R\acreated\"#\n" + + "\aPongMsg\x12\x18\n" + + "\acreated\x18\x01 \x01(\x03R\acreated\"%\n" + + "\vShutdownMsg\x12\x16\n" + + "\x06reason\x18\x01 \x01(\tR\x06reason\"/\n" + + "\x0fAuthResponseMsg\x12\x1c\n" + + "\tsignature\x18\x01 \x01(\fR\tsignature\"\xce\x01\n" + + "\x18LedgerChannelProposalMsg\x12R\n" + + "\x15base_channel_proposal\x18\x01 \x01(\v2\x1e.perunwire.BaseChannelProposalR\x13baseChannelProposal\x124\n" + + "\vparticipant\x18\x02 \x01(\v2\x12.perunwire.AddressR\vparticipant\x12(\n" + + "\x05peers\x18\x03 \x03(\v2\x12.perunwire.AddressR\x05peers\"\xb1\x01\n" + + "\x1bLedgerChannelProposalAccMsg\x12\\\n" + + "\x19base_channel_proposal_acc\x18\x01 \x01(\v2!.perunwire.BaseChannelProposalAccR\x16baseChannelProposalAcc\x124\n" + + "\vparticipant\x18\x02 \x01(\v2\x12.perunwire.AddressR\vparticipant\"\x83\x01\n" + + "\x15SubChannelProposalMsg\x12R\n" + + "\x15base_channel_proposal\x18\x01 \x01(\v2\x1e.perunwire.BaseChannelProposalR\x13baseChannelProposal\x12\x16\n" + + "\x06parent\x18\x02 \x01(\fR\x06parent\"x\n" + + "\x18SubChannelProposalAccMsg\x12\\\n" + + "\x19base_channel_proposal_acc\x18\x01 \x01(\v2!.perunwire.BaseChannelProposalAccR\x16baseChannelProposalAcc\"\x97\x02\n" + + "\x19VirtualChannelProposalMsg\x12R\n" + + "\x15base_channel_proposal\x18\x01 \x01(\v2\x1e.perunwire.BaseChannelProposalR\x13baseChannelProposal\x12.\n" + + "\bproposer\x18\x02 \x01(\v2\x12.perunwire.AddressR\bproposer\x12(\n" + + "\x05peers\x18\x03 \x03(\v2\x12.perunwire.AddressR\x05peers\x12\x18\n" + + "\aparents\x18\x04 \x03(\fR\aparents\x122\n" + + "\n" + + "index_maps\x18\x05 \x03(\v2\x13.perunwire.IndexMapR\tindexMaps\"\xae\x01\n" + + "\x1cVirtualChannelProposalAccMsg\x12\\\n" + + "\x19base_channel_proposal_acc\x18\x01 \x01(\v2!.perunwire.BaseChannelProposalAccR\x16baseChannelProposalAcc\x120\n" + + "\tresponder\x18\x02 \x01(\v2\x12.perunwire.AddressR\tresponder\"P\n" + + "\x15ChannelProposalRejMsg\x12\x1f\n" + + "\vproposal_id\x18\x01 \x01(\fR\n" + + "proposalId\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\"e\n" + + "\x10ChannelUpdateMsg\x12?\n" + + "\x0echannel_update\x18\x01 \x01(\v2\x18.perunwire.ChannelUpdateR\rchannelUpdate\x12\x10\n" + + "\x03sig\x18\x02 \x01(\fR\x03sig\"\xd1\x01\n" + + " VirtualChannelFundingProposalMsg\x12I\n" + + "\x12channel_update_msg\x18\x01 \x01(\v2\x1b.perunwire.ChannelUpdateMsgR\x10channelUpdateMsg\x120\n" + + "\ainitial\x18\x02 \x01(\v2\x16.perunwire.SignedStateR\ainitial\x120\n" + + "\tindex_map\x18\x03 \x01(\v2\x13.perunwire.IndexMapR\bindexMap\"\x9e\x01\n" + + "#VirtualChannelSettlementProposalMsg\x12I\n" + + "\x12channel_update_msg\x18\x01 \x01(\v2\x1b.perunwire.ChannelUpdateMsgR\x10channelUpdateMsg\x12,\n" + + "\x05final\x18\x02 \x01(\v2\x16.perunwire.SignedStateR\x05final\"`\n" + + "\x13ChannelUpdateAccMsg\x12\x1d\n" + + "\n" + + "channel_id\x18\x01 \x01(\fR\tchannelId\x12\x18\n" + + "\aversion\x18\x02 \x01(\x04R\aversion\x12\x10\n" + + "\x03sig\x18\x03 \x01(\fR\x03sig\"f\n" + + "\x13ChannelUpdateRejMsg\x12\x1d\n" + + "\n" + + "channel_id\x18\x01 \x01(\fR\tchannelId\x12\x18\n" + + "\aversion\x18\x02 \x01(\x04R\aversion\x12\x16\n" + + "\x06reason\x18\x03 \x01(\tR\x06reason\"]\n" + + "\x0eChannelSyncMsg\x12\x14\n" + + "\x05phase\x18\x01 \x01(\rR\x05phase\x125\n" + + "\n" + + "current_tx\x18\x02 \x01(\v2\x16.perunwire.TransactionR\tcurrentTxB&Z$perun.network/go-perun/wire/protobufb\x06proto3" var ( - file_wire_proto_rawDescOnce sync.Once - file_wire_proto_rawDescData = file_wire_proto_rawDesc + file_wire_protobuf_wire_proto_rawDescOnce sync.Once + file_wire_protobuf_wire_proto_rawDescData []byte ) -func file_wire_proto_rawDescGZIP() []byte { - file_wire_proto_rawDescOnce.Do(func() { - file_wire_proto_rawDescData = protoimpl.X.CompressGZIP(file_wire_proto_rawDescData) +func file_wire_protobuf_wire_proto_rawDescGZIP() []byte { + file_wire_protobuf_wire_proto_rawDescOnce.Do(func() { + file_wire_protobuf_wire_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_wire_protobuf_wire_proto_rawDesc), len(file_wire_protobuf_wire_proto_rawDesc))) }) - return file_wire_proto_rawDescData + return file_wire_protobuf_wire_proto_rawDescData } -var file_wire_proto_msgTypes = make([]protoimpl.MessageInfo, 32) -var file_wire_proto_goTypes = []any{ +var file_wire_protobuf_wire_proto_msgTypes = make([]protoimpl.MessageInfo, 32) +var file_wire_protobuf_wire_proto_goTypes = []any{ (*Envelope)(nil), // 0: perunwire.Envelope (*Balance)(nil), // 1: perunwire.Balance (*Balances)(nil), // 2: perunwire.Balances @@ -2615,7 +2372,7 @@ var file_wire_proto_goTypes = []any{ (*ChannelUpdateRejMsg)(nil), // 30: perunwire.ChannelUpdateRejMsg (*ChannelSyncMsg)(nil), // 31: perunwire.ChannelSyncMsg } -var file_wire_proto_depIdxs = []int32{ +var file_wire_protobuf_wire_proto_depIdxs = []int32{ 4, // 0: perunwire.Envelope.sender:type_name -> perunwire.Address 4, // 1: perunwire.Envelope.recipient:type_name -> perunwire.Address 15, // 2: perunwire.Envelope.ping_msg:type_name -> perunwire.PingMsg @@ -2676,398 +2433,12 @@ var file_wire_proto_depIdxs = []int32{ 0, // [0:53] is the sub-list for field type_name } -func init() { file_wire_proto_init() } -func file_wire_proto_init() { - if File_wire_proto != nil { +func init() { file_wire_protobuf_wire_proto_init() } +func file_wire_protobuf_wire_proto_init() { + if File_wire_protobuf_wire_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_wire_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*Envelope); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*Balance); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*Balances); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*AddressMapping); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*Address); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*IndexMap); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*SubAlloc); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[7].Exporter = func(v any, i int) any { - switch v := v.(*Allocation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[8].Exporter = func(v any, i int) any { - switch v := v.(*BaseChannelProposal); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[9].Exporter = func(v any, i int) any { - switch v := v.(*BaseChannelProposalAcc); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[10].Exporter = func(v any, i int) any { - switch v := v.(*Params); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[11].Exporter = func(v any, i int) any { - switch v := v.(*State); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[12].Exporter = func(v any, i int) any { - switch v := v.(*Transaction); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[13].Exporter = func(v any, i int) any { - switch v := v.(*SignedState); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[14].Exporter = func(v any, i int) any { - switch v := v.(*ChannelUpdate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[15].Exporter = func(v any, i int) any { - switch v := v.(*PingMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[16].Exporter = func(v any, i int) any { - switch v := v.(*PongMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[17].Exporter = func(v any, i int) any { - switch v := v.(*ShutdownMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[18].Exporter = func(v any, i int) any { - switch v := v.(*AuthResponseMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[19].Exporter = func(v any, i int) any { - switch v := v.(*LedgerChannelProposalMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[20].Exporter = func(v any, i int) any { - switch v := v.(*LedgerChannelProposalAccMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[21].Exporter = func(v any, i int) any { - switch v := v.(*SubChannelProposalMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[22].Exporter = func(v any, i int) any { - switch v := v.(*SubChannelProposalAccMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[23].Exporter = func(v any, i int) any { - switch v := v.(*VirtualChannelProposalMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[24].Exporter = func(v any, i int) any { - switch v := v.(*VirtualChannelProposalAccMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[25].Exporter = func(v any, i int) any { - switch v := v.(*ChannelProposalRejMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[26].Exporter = func(v any, i int) any { - switch v := v.(*ChannelUpdateMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[27].Exporter = func(v any, i int) any { - switch v := v.(*VirtualChannelFundingProposalMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[28].Exporter = func(v any, i int) any { - switch v := v.(*VirtualChannelSettlementProposalMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[29].Exporter = func(v any, i int) any { - switch v := v.(*ChannelUpdateAccMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[30].Exporter = func(v any, i int) any { - switch v := v.(*ChannelUpdateRejMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_wire_proto_msgTypes[31].Exporter = func(v any, i int) any { - switch v := v.(*ChannelSyncMsg); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_wire_proto_msgTypes[0].OneofWrappers = []any{ + file_wire_protobuf_wire_proto_msgTypes[0].OneofWrappers = []any{ (*Envelope_PingMsg)(nil), (*Envelope_PongMsg)(nil), (*Envelope_ShutdownMsg)(nil), @@ -3090,18 +2461,17 @@ func file_wire_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_wire_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_wire_protobuf_wire_proto_rawDesc), len(file_wire_protobuf_wire_proto_rawDesc)), NumEnums: 0, NumMessages: 32, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_wire_proto_goTypes, - DependencyIndexes: file_wire_proto_depIdxs, - MessageInfos: file_wire_proto_msgTypes, + GoTypes: file_wire_protobuf_wire_proto_goTypes, + DependencyIndexes: file_wire_protobuf_wire_proto_depIdxs, + MessageInfos: file_wire_protobuf_wire_proto_msgTypes, }.Build() - File_wire_proto = out.File - file_wire_proto_rawDesc = nil - file_wire_proto_goTypes = nil - file_wire_proto_depIdxs = nil + File_wire_protobuf_wire_proto = out.File + file_wire_protobuf_wire_proto_goTypes = nil + file_wire_protobuf_wire_proto_depIdxs = nil } diff --git a/wire/protobuf/wire.proto b/wire/protobuf/wire.proto index 63ac25e24..e379207a1 100644 --- a/wire/protobuf/wire.proto +++ b/wire/protobuf/wire.proto @@ -103,6 +103,7 @@ message BaseChannelProposal { bytes init_data = 5; Allocation init_bals = 6; Balances funding_agreement = 7; + bytes aux = 8; } // BaseChannelProposalAcc represents client.BaseChannelProposalAcc. @@ -120,6 +121,7 @@ message Params { bytes nonce = 5; bool ledger_channel = 6; bool virtual_channel = 7; + bytes aux = 8; } // State represents channel.State. diff --git a/wire/receiver.go b/wire/receiver.go index 1f4b6af7e..dac5ae904 100644 --- a/wire/receiver.go +++ b/wire/receiver.go @@ -40,6 +40,13 @@ type Receiver struct { sync.Closer } +// NewReceiver creates a new receiver. +func NewReceiver() *Receiver { + return &Receiver{ + msgs: make(chan *Envelope, receiverBufferSize), + } +} + // Next returns a channel to the next message. func (r *Receiver) Next(ctx context.Context) (*Envelope, error) { select { @@ -67,10 +74,3 @@ func (r *Receiver) Put(e *Envelope) { case <-r.Closed(): } } - -// NewReceiver creates a new receiver. -func NewReceiver() *Receiver { - return &Receiver{ - msgs: make(chan *Envelope, receiverBufferSize), - } -} diff --git a/wire/receiver_internal_test.go b/wire/receiver_internal_test.go index acf712453..b9c8c5359 100644 --- a/wire/receiver_internal_test.go +++ b/wire/receiver_internal_test.go @@ -20,6 +20,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ctxtest "polycry.pt/poly-go/context/test" ) @@ -32,7 +33,7 @@ func TestReceiver_Close(t *testing.T) { t.Parallel() r := NewReceiver() - assert.NoError(t, r.Close()) + require.NoError(t, r.Close()) assert.Error(t, r.Close()) } @@ -46,7 +47,7 @@ func TestReceiver_Next(t *testing.T) { r := NewReceiver() go r.Put(e) re, err := r.Next(context.Background()) - assert.NoError(t, err) + require.NoError(t, err) assert.Same(t, e, re) }) }) diff --git a/wire/relay.go b/wire/relay.go index 9e5afe918..881fc5711 100644 --- a/wire/relay.go +++ b/wire/relay.go @@ -124,33 +124,6 @@ func (p *Relay) Subscribe(c Consumer, predicate Predicate) error { return nil } -func (p *Relay) delete(c Consumer) { - p.mutex.Lock() - defer p.mutex.Unlock() - - if p.IsClosed() { - return - } - - for i, sub := range p.consumers { - if sub.consumer == c { - p.consumers[i] = p.consumers[len(p.consumers)-1] - p.consumers[len(p.consumers)-1] = subscription{} // For the GC. - p.consumers = p.consumers[:len(p.consumers)-1] - - return - } - } - log.Panic("deleted consumer that was not subscribed") -} - -func (p *Relay) isEmpty() bool { - p.mutex.RLock() - defer p.mutex.RUnlock() - - return len(p.consumers) == 0 -} - // Put puts an Envelope in the relay. func (p *Relay) Put(e *Envelope) { p.mutex.RLock() @@ -175,12 +148,6 @@ func (p *Relay) Put(e *Envelope) { } } -func logUnhandledMsg(e *Envelope) { - log.WithField("sender", e.Sender). - WithField("recipient", e.Recipient). - Debugf("Received %T message without subscription: %v", e.Msg, e.Msg) -} - // SetDefaultMsgHandler sets the default message handler. func (p *Relay) SetDefaultMsgHandler(handler func(*Envelope)) { if handler == nil { @@ -190,3 +157,36 @@ func (p *Relay) SetDefaultMsgHandler(handler func(*Envelope)) { defer p.mutex.Unlock() p.defaultMsgHandler = handler } + +func (p *Relay) delete(c Consumer) { + p.mutex.Lock() + defer p.mutex.Unlock() + + if p.IsClosed() { + return + } + + for i, sub := range p.consumers { + if sub.consumer == c { + p.consumers[i] = p.consumers[len(p.consumers)-1] + p.consumers[len(p.consumers)-1] = subscription{} // For the GC. + p.consumers = p.consumers[:len(p.consumers)-1] + + return + } + } + log.Panic("deleted consumer that was not subscribed") +} + +func (p *Relay) isEmpty() bool { + p.mutex.RLock() + defer p.mutex.RUnlock() + + return len(p.consumers) == 0 +} + +func logUnhandledMsg(e *Envelope) { + log.WithField("sender", e.Sender). + WithField("recipient", e.Recipient). + Debugf("Received %T message without subscription: %v", e.Msg, e.Msg) +} diff --git a/wire/relay_internal_test.go b/wire/relay_internal_test.go index 3e6fcd6ae..63fbfdd98 100644 --- a/wire/relay_internal_test.go +++ b/wire/relay_internal_test.go @@ -36,13 +36,13 @@ func TestProducer(t *testing.T) { pred := func(*Envelope) bool { return true } assert.True(t, p.isEmpty()) - assert.NoError(t, p.Subscribe(r0, pred)) + require.NoError(t, p.Subscribe(r0, pred)) assert.False(t, p.isEmpty()) - assert.NoError(t, p.Subscribe(r1, pred)) - assert.NoError(t, p.Subscribe(r2, pred)) - assert.Equal(t, len(p.consumers), 3) + require.NoError(t, p.Subscribe(r1, pred)) + require.NoError(t, p.Subscribe(r2, pred)) + assert.Len(t, p.consumers, 3) p.delete(r0) - assert.Equal(t, len(p.consumers), 2) + assert.Len(t, p.consumers, 2) assert.False(t, p.isEmpty()) assert.Panics(t, func() { p.delete(r0) }) } @@ -62,10 +62,10 @@ func TestProducer_SetDefaultMsgHandler(t *testing.T) { func TestProducer_Close(t *testing.T) { p := NewRelay() - assert.NoError(t, p.Close()) + require.NoError(t, p.Close()) err := p.Close() - assert.Error(t, err) + require.Error(t, err) assert.True(t, sync.IsAlreadyClosedError(err)) assert.NotPanics(t, func() { p.delete(nil) }, @@ -83,7 +83,7 @@ func TestProducer_Subscribe(t *testing.T) { t.Run("duplicate", func(t *testing.T) { p := NewRelay() r := NewReceiver() - assert.NoError(t, p.Subscribe(r, fn)) + require.NoError(t, p.Subscribe(r, fn)) assert.Panics(t, func() { p.Subscribe(r, fn) }) //nolint:errcheck }) @@ -120,7 +120,7 @@ func TestProducer_caching(t *testing.T) { prod.Put(ping0) assert.Equal(1, prod.cache.Size()) - assert.Len(unhandlesMsg, 0) + assert.Empty(unhandlesMsg) prod.Put(pong1) assert.Equal(1, prod.cache.Size()) @@ -135,7 +135,7 @@ func TestProducer_caching(t *testing.T) { prod.Subscribe(rec, isPing) //nolint:errcheck ctxtest.AssertTerminates(t, timeout, func() { e, err := rec.Next(ctx) - assert.NoError(err) + require.NoError(t, err) assert.Same(e, ping0) }) assert.Equal(1, prod.cache.Size()) diff --git a/wire/relay_test.go b/wire/relay_test.go index 5f33ff090..a66a52707 100644 --- a/wire/relay_test.go +++ b/wire/relay_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "perun.network/go-perun/wire" wiretest "perun.network/go-perun/wire/test" "polycry.pt/poly-go/test" @@ -27,7 +28,7 @@ func TestProducer_produce_closed(t *testing.T) { var missed *wire.Envelope p := wire.NewRelay() p.SetDefaultMsgHandler(func(e *wire.Envelope) { missed = e }) - assert.NoError(t, p.Close()) + require.NoError(t, p.Close()) rng := test.Prng(t) a := wiretest.NewRandomAddress(rng) b := wiretest.NewRandomAddress(rng) diff --git a/wire/test/address.go b/wire/test/address.go index 6df58e200..6037639de 100644 --- a/wire/test/address.go +++ b/wire/test/address.go @@ -36,8 +36,8 @@ func TestAddressImplementation(t *testing.T, newAddress wire.NewAddressFunc, new // Test Address.MarshalBinary and UnmarshalBinary. data, err := addr.MarshalBinary() - assert.NoError(err) - assert.NoError(addr.UnmarshalBinary(data), "Byte deserialization of address should work") + require.NoError(err) + require.NoError(addr.UnmarshalBinary(data), "Byte deserialization of address should work") // Test Address.Equals. null := newAddress() @@ -51,9 +51,9 @@ func TestAddressImplementation(t *testing.T, newAddress wire.NewAddressFunc, new // Test Address.Bytes. addrBytes, err := addr.MarshalBinary() - assert.NoError(err, "Marshaling address should not error") + require.NoError(err, "Marshaling address should not error") nullBytes, err := null.MarshalBinary() - assert.NoError(err, "Marshaling zero address should not error") + require.NoError(err, "Marshaling zero address should not error") assert.False(bytes.Equal(addrBytes, nullBytes), "Expected inequality of byte representations of nonzero and zero address") // a.Equal(Decode(Encode(a))) diff --git a/wire/test/bustest.go b/wire/test/bustest.go index 2f871d3f1..6403fa1de 100644 --- a/wire/test/bustest.go +++ b/wire/test/bustest.go @@ -21,6 +21,7 @@ import ( "perun.network/go-perun/wallet" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "perun.network/go-perun/wire" @@ -48,7 +49,7 @@ func GenericBusTest(t *testing.T, ) { t.Helper() require.Greater(t, numClients, 1) - require.Greater(t, numMsgs, 0) + require.Positive(t, numMsgs) rng := test.Prng(t) type Client struct { @@ -72,14 +73,13 @@ func GenericBusTest(t *testing.T, ctx, cancel := context.WithTimeout(context.Background(), testNoReceiveTimeout) defer cancel() for i := range clients { - i := i go ct.StageN("receive timeout", numClients, func(t test.ConcT) { r := wire.NewReceiver() defer r.Close() err := clients[i].r.Subscribe(r, func(e *wire.Envelope) bool { return true }) - require.NoError(t, err) + assert.NoError(t, err) _, err = r.Next(ctx) - require.Error(t, err) + assert.Error(t, err) }) } ct.Wait("receive timeout") @@ -98,7 +98,6 @@ func GenericBusTest(t *testing.T, if sender == recipient { continue } - sender, recipient := sender, recipient origEnv := &wire.Envelope{ Sender: wire.AddressMapfromAccountMap(clients[sender].id), Recipient: wire.AddressMapfromAccountMap(clients[recipient].id), @@ -113,16 +112,16 @@ func GenericBusTest(t *testing.T, go ct.StageN("receive", numClients*(numClients-1), func(t test.ConcT) { defer recv.Close() - for i := 0; i < numMsgs; i++ { + for range numMsgs { e, err := recv.Next(ctx) - require.NoError(t, err) - require.Equal(t, e, origEnv) + assert.NoError(t, err) + assert.Equal(t, e, origEnv) } }) go ct.StageN("publish", numClients*(numClients-1), func(t test.ConcT) { - for i := 0; i < numMsgs; i++ { + for range numMsgs { err := clients[sender].pub.Publish(ctx, origEnv) - require.NoError(t, err) + assert.NoError(t, err) } }) }