Skip to content

Commit

Permalink
Merge branch 'main' into feat-egoistic-funding
Browse files Browse the repository at this point in the history
  • Loading branch information
sophia1ch authored Mar 12, 2024
2 parents 49cd2cf + 61ed2dc commit 53e92e9
Show file tree
Hide file tree
Showing 37 changed files with 904 additions and 208 deletions.
47 changes: 45 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,49 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [0.11.0] Kiviuq - 2024-02-21 [:boom:]
Exposure of protobuf converters & `SignedState`, abstraction of tests and bug fixes.

## Added
- Add Fabric to backend list in README: [#377]
- Create new type `TransparentChannel` to expose `SignedState`: [#389]
- Update backend compatibility list in README: [#392]
- Add MAINTAINERS.md file, Update NOTICE: [#394]

## Fixed
- Fix sub-channel test: [#359]
- Fix Multi-Adjudicator Subscription: [#366]
- Use correct identity for client tests: [#376]
- Fix link to white paper in README: [#379]
- Fix linter copyright year checking in CI: [#389]
- Fix failing unit tests: [#399]

## Changed [:boom:]
- Abstract multiledger test, making it usable by backends: [#355]
- Abstract fund recovery test, making it usable by backends: [#370]
- Abstract virtual channel test, making it usable by backends: [#375]
- Expose protobuf converters: [#384] [#393]
- Use absolute module path in wire.proto: [#383]
- Create AppID Type to generalize app identifiers: [#378] [:boom:]


[#359]: https://github.com/hyperledger-labs/go-perun/pull/359
[#355]: https://github.com/hyperledger-labs/go-perun/pull/355
[#366]: https://github.com/hyperledger-labs/go-perun/pull/366
[#370]: https://github.com/hyperledger-labs/go-perun/pull/370
[#375]: https://github.com/hyperledger-labs/go-perun/pull/375
[#376]: https://github.com/hyperledger-labs/go-perun/pull/376
[#377]: https://github.com/hyperledger-labs/go-perun/pull/377
[#378]: https://github.com/hyperledger-labs/go-perun/pull/378
[#379]: https://github.com/hyperledger-labs/go-perun/pull/379
[#383]: https://github.com/hyperledger-labs/go-perun/pull/383
[#384]: https://github.com/hyperledger-labs/go-perun/pull/384
[#389]: https://github.com/hyperledger-labs/go-perun/pull/389
[#392]: https://github.com/hyperledger-labs/go-perun/pull/392
[#393]: https://github.com/hyperledger-labs/go-perun/pull/393
[#394]: https://github.com/hyperledger-labs/go-perun/pull/394
[#399]: https://github.com/hyperledger-labs/go-perun/pull/399


## [0.10.0] Janus - 2022-05-25 [:warning:]
Multi-ledger payment channels.
Expand Down Expand Up @@ -389,7 +431,8 @@ Initial release.
[:warning:]: #warning
[:boom:]: #breaking

[Unreleased]: https://github.com/hyperledger-labs/go-perun/compare/v0.10.0...HEAD
[Unreleased]: https://github.com/hyperledger-labs/go-perun/compare/v0.11.0...HEAD
[0.11.0]: https://github.com/hyperledger-labs/go-perun/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/hyperledger-labs/go-perun/compare/v0.9.1...v0.10.0
[0.9.1]: https://github.com/hyperledger-labs/go-perun/compare/v0.9.0...v0.9.1
[0.9.0]: https://github.com/hyperledger-labs/go-perun/compare/v0.8.0...v0.9.0
Expand Down
5 changes: 5 additions & 0 deletions backend/sim/wire/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func (acc *Account) Address() wire.Address {
return acc.addr
}

// Sign signs the given message with the account's private key.
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{
Expand Down
9 changes: 9 additions & 0 deletions backend/sim/wire/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package wire

import (
"bytes"
"errors"
"math/rand"

"perun.network/go-perun/wire"
Expand Down Expand Up @@ -62,6 +63,14 @@ func (a Address) Cmp(b wire.Address) int {
return bytes.Compare(a[:], bTyped[:])
}

// Verify verifies a signature.
func (a Address) Verify(msg, sig []byte) error {
if !bytes.Equal(sig, []byte("Authenticate")) {
return errors.New("invalid signature")
}
return nil
}

// NewRandomAddress returns a new random peer address.
func NewRandomAddress(rng *rand.Rand) *Address {
addr := Address{}
Expand Down
5 changes: 4 additions & 1 deletion backend/sim/wire/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Package wire contains the implementation of the wire interfaces.
// Package wire is used for internal tests in the packages channel, wire, and client.
// Note that Account.Sign and Address.Verify are mock methods.
// We use the backend/wire/sim mock implementation for testing other go-perun functionalities.
// Our default wire.Account and wire.Address implementations can be found in wire/net/simple and are used for our applications.
package wire // import "perun.network/go-perun/backend/sim/wire"
2 changes: 1 addition & 1 deletion client/adjudicate.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ func (c *Channel) Settle(ctx context.Context, secondary bool) (err error) {
// Withdraw.
err = c.withdraw(ctx, secondary)
if err != nil {
return
return err
}

// Set phase `Withdrawn`.
Expand Down
2 changes: 1 addition & 1 deletion client/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ func (c *Client) validTwoPartyProposal(
multiLedger := multi.IsMultiLedgerAssets(proposal.Base().InitBals.Assets)
appChannel := !channel.IsNoApp(proposal.Base().App)
if multiLedger && appChannel {
return fmt.Errorf("multi-ledger app channel not supported")
return errors.New("multi-ledger app channel not supported")
}

peers := c.proposalPeers(proposal)
Expand Down
3 changes: 2 additions & 1 deletion client/virtual_channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,8 @@ func (c *Client) matchFundingProposal(ctx context.Context, a, b interface{}) boo
}

go func() {
err := virtual.watchVirtual() //nolint:contextcheck // The context will be derived from the channel context.
// The context will be derived from the channel context.
err := virtual.watchVirtual() //nolint:contextcheck
c.log.Debugf("channel %v: watcher stopped: %v", virtual.ID(), err)
}()
return true
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ require (
go.uber.org/goleak v1.1.11
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/protobuf v1.23.0
google.golang.org/protobuf v1.32.0
polycry.pt/poly-go v0.0.0-20220222131629-aa4bdbaab60b
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.4 // indirect
github.com/google/uuid v1.6.0
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
9 changes: 6 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
Expand Down Expand Up @@ -116,8 +117,10 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
4 changes: 2 additions & 2 deletions wallet/test/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ func TestAddress(t *testing.T, s *Setup) { //nolint:revive // `test.Test...` stu
// Test Address.String.
nullString := null.String()
addrString := addr.String()
assert.Greater(t, len(nullString), 0)
assert.Greater(t, len(addrString), 0)
assert.NotEmpty(t, nullString)
assert.NotEmpty(t, addrString)
assert.NotEqual(t, addrString, nullString)

// Test Address.Equals.
Expand Down
2 changes: 1 addition & 1 deletion wallet/test/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestAccountWithWalletAndBackend(t *testing.T, s *Setup) { //nolint:revive /
t.Error("Verification of invalid signature should produce error or return false")
}
// Expand the signature and check for error
// nolint:gocritic
//nolint:gocritic
tampered = append(sig, 0)
valid, err = s.Backend.VerifySignature(s.DataToSign, tampered, acc.Address())
if valid && err != nil {
Expand Down
6 changes: 3 additions & 3 deletions wallet/test/walletbench.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func GenericAccountBenchmark(b *testing.B, s *Setup) {
func benchAccountSign(b *testing.B, s *Setup) {
b.Helper()
perunAcc, err := s.Wallet.Unlock(s.AddressInWallet)
require.Nil(b, err)
require.NoError(b, err)

for n := 0; n < b.N; n++ {
_, err := perunAcc.SignData(s.DataToSign)
Expand All @@ -56,9 +56,9 @@ func benchBackendVerifySig(b *testing.B, s *Setup) {
// We dont want to measure the SignDataWithPW here, just need it for the verification
b.StopTimer()
perunAcc, err := s.Wallet.Unlock(s.AddressInWallet)
require.Nil(b, err)
require.NoError(b, err)
signature, err := perunAcc.SignData(s.DataToSign)
require.Nil(b, err)
require.NoError(b, err)
b.StartTimer()

for n := 0; n < b.N; n++ {
Expand Down
47 changes: 41 additions & 6 deletions wire/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package wire

import (
"encoding/binary"
"fmt"
"io"
)

Expand All @@ -31,31 +33,64 @@ func init() {
type Account interface {
// Address used by this account.
Address() Address

// Sign signs the given message with this account's private key.
Sign(msg []byte) ([]byte, error)
}

var _ Msg = (*AuthResponseMsg)(nil)

// AuthResponseMsg is the response message in the peer authentication protocol.
//
// This will be expanded later to contain signatures.
type AuthResponseMsg struct{}
type AuthResponseMsg struct {
Signature []byte
}

// Type returns AuthResponse.
func (m *AuthResponseMsg) Type() Type {
return AuthResponse
}

// Encode encodes this AuthResponseMsg into an io.Writer.
// It writes the signature to the writer.
func (m *AuthResponseMsg) Encode(w io.Writer) error {
return nil
// Write the length of the signature
err := binary.Write(w, binary.BigEndian, uint32(len(m.Signature)))
if err != nil {
return fmt.Errorf("failed to write signature length: %w", err)
}
// Write the signature itself
_, err = w.Write(m.Signature)
return err
}

// Decode decodes an AuthResponseMsg from an io.Reader.
// It reads the signature from the reader.
func (m *AuthResponseMsg) Decode(r io.Reader) (err error) {
// Read the length of the signature
var signatureLen uint32
if err := binary.Read(r, binary.BigEndian, &signatureLen); err != nil {
return fmt.Errorf("failed to read signature length: %w", err)
}
// Read the signature bytes
m.Signature = make([]byte, signatureLen)
if _, err := io.ReadFull(r, m.Signature); err != nil {
return fmt.Errorf("failed to read signature: %w", err)
}
return nil
}

// NewAuthResponseMsg creates an authentication response message.
func NewAuthResponseMsg(_ Account) Msg {
return &AuthResponseMsg{}
func NewAuthResponseMsg(acc Account) (Msg, error) {
addressBytes, err := acc.Address().MarshalBinary()
if err != nil {
return nil, fmt.Errorf("failed to marshal address: %w", err)
}
signature, err := acc.Sign(addressBytes)
if err != nil {
return nil, fmt.Errorf("failed to sign address: %w", err)
}

return &AuthResponseMsg{
Signature: signature,
}, nil
}
3 changes: 3 additions & 0 deletions wire/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ type Address interface {
// Cmp compares the byte representation of two addresses. For `a.Cmp(b)`
// returns -1 if a < b, 0 if a == b, 1 if a > b.
Cmp(Address) int
// Verify verifies a message signature.
// It returns an error if the signature is invalid.
Verify(msg []byte, sig []byte) error
}

// Addresses is a helper type for encoding and decoding address slices in
Expand Down
2 changes: 1 addition & 1 deletion wire/cache_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestCache(t *testing.T) {
assert.Equal(2, c.Size())

empty := c.Messages(func(*Envelope) bool { return false })
assert.Len(empty, 0)
assert.Empty(empty)

c.Release(&isPing)
assert.False(c.Put(ping2), "Put into cache with canceled predicate")
Expand Down
31 changes: 29 additions & 2 deletions wire/net/exchange_addr.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,15 @@ func IsAuthenticationError(err error) bool {
func ExchangeAddrsActive(ctx context.Context, id wire.Account, peer wire.Address, conn Conn) error {
var err error
ok := pkg.TerminatesCtx(ctx, func() {
authMsg, err2 := wire.NewAuthResponseMsg(id)
if err2 != nil {
err = errors.WithMessage(err2, "creating auth message")
return
}
err = conn.Send(&wire.Envelope{
Sender: id.Address(),
Recipient: peer,
Msg: wire.NewAuthResponseMsg(id),
Msg: authMsg,
})
if err != nil {
err = errors.WithMessage(err, "sending message")
Expand All @@ -74,6 +79,8 @@ func ExchangeAddrsActive(ctx context.Context, id wire.Account, peer wire.Address
err = errors.WithMessage(err, "receiving message")
} else if _, ok := e.Msg.(*wire.AuthResponseMsg); !ok {
err = errors.Errorf("expected AuthResponse wire msg, got %v", e.Msg.Type())
} else if check := VerifyAddressSignature(peer, e.Msg.(*wire.AuthResponseMsg).Signature); check != nil {
err = errors.WithMessage(err, "verifying peer address's signature")
} else if !e.Recipient.Equal(id.Address()) &&
!e.Sender.Equal(peer) {
err = NewAuthenticationError(e.Sender, e.Recipient, id.Address(), "unmatched response sender or recipient")
Expand Down Expand Up @@ -101,14 +108,23 @@ func ExchangeAddrsPassive(ctx context.Context, id wire.Account, conn Conn) (wire
err = errors.Errorf("expected AuthResponse wire msg, got %v", e.Msg.Type())
} else if !e.Recipient.Equal(id.Address()) {
err = NewAuthenticationError(e.Sender, e.Recipient, id.Address(), "unmatched response sender or recipient")
} else if err = VerifyAddressSignature(e.Sender, e.Msg.(*wire.AuthResponseMsg).Signature); err != nil {
err = errors.WithMessage(err, "verifying peer address's signature")
}

if err != nil {
return
}

authMsg, err2 := wire.NewAuthResponseMsg(id)
if err2 != nil {
err = errors.WithMessage(err2, "creating auth message")
return
}
addr, err = e.Sender, conn.Send(&wire.Envelope{
Sender: id.Address(),
Recipient: e.Sender,
Msg: wire.NewAuthResponseMsg(id),
Msg: authMsg,
})
})

Expand All @@ -120,3 +136,14 @@ func ExchangeAddrsPassive(ctx context.Context, id wire.Account, conn Conn) (wire
}
return addr, err
}

// VerifyAddressSignature verifies a signature against the hash of an address.
// It relies on the MarshalBinary method of the provided wire.Address interface to generate the address hash.
// In case the MarshalBinary method doesn't produce the expected hash, the verification may fail.
func VerifyAddressSignature(addr wire.Address, sig []byte) error {
addressBytes, err := addr.MarshalBinary()
if err != nil {
return fmt.Errorf("failed to marshal address: %w", err)
}
return addr.Verify(addressBytes, sig)
}
Loading

0 comments on commit 53e92e9

Please sign in to comment.