203 lines
4.0 KiB
Go
203 lines
4.0 KiB
Go
package messagesigner
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/filecoin-project/lotus/chain/wallet"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
ds_sync "github.com/ipfs/go-datastore/sync"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
"github.com/ipfs/go-datastore"
|
|
)
|
|
|
|
type mockMpool struct {
|
|
lk sync.RWMutex
|
|
nonces map[address.Address]uint64
|
|
}
|
|
|
|
var _ MpoolNonceAPI = (*mockMpool)(nil)
|
|
|
|
func newMockMpool() *mockMpool {
|
|
return &mockMpool{nonces: make(map[address.Address]uint64)}
|
|
}
|
|
|
|
func (mp *mockMpool) setNonce(addr address.Address, nonce uint64) {
|
|
mp.lk.Lock()
|
|
defer mp.lk.Unlock()
|
|
|
|
mp.nonces[addr] = nonce
|
|
}
|
|
|
|
func (mp *mockMpool) GetNonce(_ context.Context, addr address.Address, _ types.TipSetKey) (uint64, error) {
|
|
mp.lk.RLock()
|
|
defer mp.lk.RUnlock()
|
|
|
|
return mp.nonces[addr], nil
|
|
}
|
|
|
|
func TestMessageSignerSignMessage(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
|
|
from1, err := w.WalletNew(ctx, types.KTSecp256k1)
|
|
require.NoError(t, err)
|
|
from2, err := w.WalletNew(ctx, types.KTSecp256k1)
|
|
require.NoError(t, err)
|
|
to1, err := w.WalletNew(ctx, types.KTSecp256k1)
|
|
require.NoError(t, err)
|
|
to2, err := w.WalletNew(ctx, types.KTSecp256k1)
|
|
require.NoError(t, err)
|
|
|
|
type msgSpec struct {
|
|
msg *types.Message
|
|
mpoolNonce [1]uint64
|
|
expNonce uint64
|
|
cbErr error
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
msgs []msgSpec
|
|
}{{
|
|
// No nonce yet in datastore
|
|
name: "no nonce yet",
|
|
msgs: []msgSpec{{
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
expNonce: 0,
|
|
}},
|
|
}, {
|
|
// Get nonce value of zero from mpool
|
|
name: "mpool nonce zero",
|
|
msgs: []msgSpec{{
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
mpoolNonce: [1]uint64{0},
|
|
expNonce: 0,
|
|
}},
|
|
}, {
|
|
// Get non-zero nonce value from mpool
|
|
name: "mpool nonce set",
|
|
msgs: []msgSpec{{
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
mpoolNonce: [1]uint64{5},
|
|
expNonce: 5,
|
|
}, {
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
// Should adjust datastore nonce because mpool nonce is higher
|
|
mpoolNonce: [1]uint64{10},
|
|
expNonce: 10,
|
|
}},
|
|
}, {
|
|
// Nonce should increment independently for each address
|
|
name: "nonce increments per address",
|
|
msgs: []msgSpec{{
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
expNonce: 0,
|
|
}, {
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
expNonce: 1,
|
|
}, {
|
|
msg: &types.Message{
|
|
To: to2,
|
|
From: from2,
|
|
},
|
|
mpoolNonce: [1]uint64{5},
|
|
expNonce: 5,
|
|
}, {
|
|
msg: &types.Message{
|
|
To: to2,
|
|
From: from2,
|
|
},
|
|
expNonce: 6,
|
|
}, {
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
expNonce: 2,
|
|
}},
|
|
}, {
|
|
name: "recover from callback error",
|
|
msgs: []msgSpec{{
|
|
// No nonce yet in datastore
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
expNonce: 0,
|
|
}, {
|
|
// Increment nonce
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
expNonce: 1,
|
|
}, {
|
|
// Callback returns error
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
cbErr: xerrors.Errorf("err"),
|
|
}, {
|
|
// Callback successful, should increment nonce in datastore
|
|
msg: &types.Message{
|
|
To: to1,
|
|
From: from1,
|
|
},
|
|
expNonce: 2,
|
|
}},
|
|
}}
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mpool := newMockMpool()
|
|
ds := ds_sync.MutexWrap(datastore.NewMapDatastore())
|
|
ms := NewMessageSigner(w, mpool, ds)
|
|
|
|
for _, m := range tt.msgs {
|
|
if len(m.mpoolNonce) == 1 {
|
|
mpool.setNonce(m.msg.From, m.mpoolNonce[0])
|
|
}
|
|
merr := m.cbErr
|
|
smsg, err := ms.SignMessage(ctx, m.msg, func(message *types.SignedMessage) error {
|
|
return merr
|
|
})
|
|
|
|
if m.cbErr != nil {
|
|
require.Error(t, err)
|
|
require.Nil(t, smsg)
|
|
} else {
|
|
require.NoError(t, err)
|
|
require.Equal(t, m.expNonce, smsg.Message.Nonce)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|