Skip to content

Commit

Permalink
Transaction Policy List (#91)
Browse files Browse the repository at this point in the history
* core.SigningOrchestrator race fix attempt

* signing-service: SignContext

* guard: SignContext

* Wallet return error on signer fail

* Remove AuxData

* Restore AuxData - it needs to stay for transitory period

* Fix: SigningOrchestrator race 2

* Fix: SigningOrchestrator no signature for not first

* Fix: Wallet.SignDigest inner build signature

* Fix: Wallet.SignDigest inner build signature

* Fix: GuardSigningService not first

* GuardSigningService unit tests

* Use v0.10.0 webrpc generated signing-service api

* Wallet.SignMessage: SignContext.WalletAddress not set

* Wallet add unit test testing SignContext expectations
  • Loading branch information
marino39 authored Aug 10, 2023
1 parent bdd276a commit aa12765
Show file tree
Hide file tree
Showing 12 changed files with 784 additions and 549 deletions.
9 changes: 8 additions & 1 deletion core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ type SignerSignature struct {
Subdigest Subdigest
Type SignerSignatureType
Signature []byte
Error error
}

// ErrSigningFunctionNotReady is returned when a signing function is not ready to sign and should be retried later.
var ErrSigningFunctionNotReady = fmt.Errorf("signing function not ready")
var ErrSigningNoSigner = fmt.Errorf("no signer")

type SigningFunction func(ctx context.Context, signer common.Address, signatures []SignerSignature) (SignerSignatureType, []byte, error)

Expand All @@ -142,6 +144,8 @@ func SigningOrchestrator(ctx context.Context, signers map[common.Address]uint16,
var signatures = make([]SignerSignature, 0, len(signers))
var signaturesExpected = len(signers)
for signer := range signers {
rSigner := signer

wg.Add(1)
go func(signer common.Address) {
defer wg.Done()
Expand Down Expand Up @@ -177,13 +181,16 @@ func SigningOrchestrator(ctx context.Context, signers map[common.Address]uint16,

retries++
continue
} else if errors.Is(err, ErrSigningNoSigner) {
err = nil
}
}

signerSignature := SignerSignature{
Type: signatureType,
Signer: signer,
Signature: signature,
Error: err,
}

cond.L.Lock()
Expand All @@ -194,7 +201,7 @@ func SigningOrchestrator(ctx context.Context, signers map[common.Address]uint16,
cond.Broadcast()
break
}
}(signer)
}(rSigner)
}

wg.Wait()
Expand Down
4 changes: 4 additions & 0 deletions core/v1/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,10 @@ func (c *WalletConfig) BuildSignature(ctx context.Context, sign core.SigningFunc

for range signerWeights {
signerSig := <-signerSignatureCh
if signerSig.Error != nil {
signCancel()
return nil, fmt.Errorf("signer %s signing error: %w", signerSig.Signer.Hex(), signerSig.Error)
}

if signerSig.Signature != nil {
signerSignatures[signerSig.Signer] = signerSignature{
Expand Down
8 changes: 8 additions & 0 deletions core/v2/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,10 @@ func (c *WalletConfig) BuildRegularSignature(ctx context.Context, sign core.Sign

for range configSigners {
signerSig := <-signerSignatureCh
if signerSig.Error != nil {
signCancel()
return nil, fmt.Errorf("signer %s signing error: %w", signerSig.Signer.Hex(), signerSig.Error)
}

if signerSig.Signature != nil {
signerSignatures[signerSig.Signer] = signerSignature{signerSig.Signer,
Expand Down Expand Up @@ -1566,6 +1570,10 @@ func (c *WalletConfig) BuildNoChainIDSignature(ctx context.Context, sign core.Si

for range configSigners {
signerSig := <-signerSignatureCh
if signerSig.Error != nil {
signCancel()
return nil, fmt.Errorf("signer %s signing error: %w", signerSig.Signer.Hex(), signerSig.Error)
}

if signerSig.Signature != nil {
signerSignatures[signerSig.Signer] = signerSignature{signerSig.Signer,
Expand Down
2 changes: 1 addition & 1 deletion estimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ func (e *Estimator) BuildStubSignature(walletConfig core.WalletConfig, willSign,
return core.SignerSignatureTypeEIP1271, sig, nil
}
} else {
return 0, nil, fmt.Errorf("no signature")
return 0, nil, core.ErrSigningNoSigner
}
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ require (
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/spf13/cobra v1.6.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230124195608-d38c7dcee874 // indirect
Expand Down
10 changes: 5 additions & 5 deletions guard/guard.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package guard

import (
"context"
"fmt"
"math/big"

"github.com/0xsequence/ethkit/go-ethereum/common"
"github.com/0xsequence/go-sequence"
"github.com/0xsequence/go-sequence/core"
"github.com/0xsequence/go-sequence/signing_service"
)
Expand All @@ -25,12 +25,12 @@ func NewGuardSigningService(params GuardSigningServiceParams) *GuardSigningServi
}

func (g *GuardSigningService) SignDigest(ctx context.Context, digest common.Hash, optChainID ...*big.Int) ([]byte, core.Signature[core.WalletConfig], error) {
auxData, err := sequence.AuxDataFromContext(ctx)
if err != nil {
return nil, nil, err
signContext := signing_service.SignContextFromContext(ctx)
if signContext == nil {
return nil, nil, fmt.Errorf("guard: missing sign context")
}

if len(auxData.Sig) == 0 {
if len(signContext.Signature) <= 2 {
return nil, nil, core.ErrSigningFunctionNotReady
}

Expand Down
131 changes: 131 additions & 0 deletions guard/guard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package guard

import (
"context"
"errors"
"math/big"
"testing"

"github.com/0xsequence/ethkit/go-ethereum/common"
"github.com/0xsequence/go-sequence"
"github.com/0xsequence/go-sequence/core"
"github.com/0xsequence/go-sequence/signing_service"
proto_signing_service "github.com/0xsequence/go-sequence/signing_service/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

type MockSigningServiceClient struct {
mock.Mock
}

func (m *MockSigningServiceClient) Ping(ctx context.Context) (bool, error) {
//TODO implement me
panic("implement me")
}

func (m *MockSigningServiceClient) Version(ctx context.Context) (*proto_signing_service.Version, error) {
//TODO implement me
panic("implement me")
}

func (m *MockSigningServiceClient) RuntimeStatus(ctx context.Context) (*proto_signing_service.RuntimeStatus, error) {
//TODO implement me
panic("implement me")
}

func (m *MockSigningServiceClient) GetSignerConfig(ctx context.Context, signer string) (*proto_signing_service.WalletConfig, error) {
//TODO implement me
panic("implement me")
}

func (m *MockSigningServiceClient) Sign(ctx context.Context, request *proto_signing_service.SignRequest) (string, error) {
//TODO implement me
panic("implement me")
}

func (m *MockSigningServiceClient) SignWith(ctx context.Context, signer string, request *proto_signing_service.SignRequest) (string, error) {
args := m.Called(ctx, signer, request)
return args.String(0), args.Error(1)
}

var _ proto_signing_service.SigningService = &MockSigningServiceClient{}

func TestGuardSigningServiceSign(t *testing.T) {
mockSigningServiceClient := &MockSigningServiceClient{}

guardSigningService := NewGuardSigningService(GuardSigningServiceParams{
SigningServiceParams: signing_service.SigningServiceParams{
SignerAddress: common.Address{},
SignerWeight: 0,
Client: mockSigningServiceClient,
},
})

mockSigningServiceClient.On("SignWith", mock.Anything, mock.Anything, mock.Anything).Return("0x01", nil)

ctx := signing_service.ContextWithSignContext(context.Background(), &proto_signing_service.SignContext{
Signature: "0x01",
})

msg := []byte("hello world")
digest := sequence.MessageDigest(msg)

sigBytes, _, err := guardSigningService.SignDigest(ctx, digest, big.NewInt(1))
require.NoError(t, err)
assert.NotEmpty(t, sigBytes)
}

func TestGuardSigningServiceSignNoSignContext(t *testing.T) {
mockSigningServiceClient := &MockSigningServiceClient{}

guardSigningService := NewGuardSigningService(GuardSigningServiceParams{
SigningServiceParams: signing_service.SigningServiceParams{
SignerAddress: common.Address{},
SignerWeight: 0,
Client: mockSigningServiceClient,
},
})

msg := []byte("hello world")
digest := sequence.MessageDigest(msg)

sigBytes, sigTyped, err := guardSigningService.SignDigest(context.Background(), digest, big.NewInt(1))
require.Error(t, err)
assert.Nil(t, sigBytes)
assert.Nil(t, sigTyped)
}

func TestGuardSigningServiceSignNotFirst(t *testing.T) {
mockSigningServiceClient := &MockSigningServiceClient{}

guardSigningService := NewGuardSigningService(GuardSigningServiceParams{
SigningServiceParams: signing_service.SigningServiceParams{
SignerAddress: common.Address{},
SignerWeight: 0,
Client: mockSigningServiceClient,
},
})

ctx := signing_service.ContextWithSignContext(context.Background(), &proto_signing_service.SignContext{})

msg := []byte("hello world")
digest := sequence.MessageDigest(msg)

sigBytes, sigTyped, err := guardSigningService.SignDigest(ctx, digest, big.NewInt(1))
require.Error(t, err)
require.True(t, errors.Is(err, core.ErrSigningFunctionNotReady))
assert.Nil(t, sigBytes)
assert.Nil(t, sigTyped)

ctx = signing_service.ContextWithSignContext(context.Background(), &proto_signing_service.SignContext{
Signature: "0x",
})

sigBytes, sigTyped, err = guardSigningService.SignDigest(ctx, digest, big.NewInt(1))
require.Error(t, err)
require.True(t, errors.Is(err, core.ErrSigningFunctionNotReady))
assert.Nil(t, sigBytes)
assert.Nil(t, sigTyped)
}
25 changes: 22 additions & 3 deletions relayer/rpc_relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func (r *RpcRelayer) Wait(ctx context.Context, metaTxnID sequence.MetaTxnID, opt
}

func (r *RpcRelayer) protoConfig(ctx context.Context, config core.WalletConfig, walletAddress common.Address) (*proto.WalletConfig, error) {
if walletConfigV1 := config.(*v1.WalletConfig); walletConfigV1 != nil {
if walletConfigV1, ok := config.(*v1.WalletConfig); ok {
var signers []*proto.WalletSigner
for _, signer := range walletConfigV1.Signers_ {
signers = append(signers, &proto.WalletSigner{
Expand All @@ -207,8 +207,27 @@ func (r *RpcRelayer) protoConfig(ctx context.Context, config core.WalletConfig,
Threshold: walletConfigV1.Threshold_,
ChainId: &chainID,
}, nil
} else if walletConfigV2 := config.(*v2.WalletConfig); walletConfigV2 != nil {
// todo: implement v2
} else if walletConfigV2, ok := config.(*v2.WalletConfig); ok {
var signers []*proto.WalletSigner
for address, weight := range walletConfigV2.Signers() {
signers = append(signers, &proto.WalletSigner{
Address: address.Hex(),
Weight: uint8(weight),
})
}

result, err := r.provider.ChainID(ctx)
if err != nil {
return nil, err
}
chainID := result.Uint64()

return &proto.WalletConfig{
Address: walletAddress.Hex(),
Signers: signers,
Threshold: walletConfigV2.Threshold_,
ChainId: &chainID,
}, nil
}

return nil, fmt.Errorf("relayer: unknown wallet config version")
Expand Down
Loading

0 comments on commit aa12765

Please sign in to comment.