112 lines
3.0 KiB
Go
112 lines
3.0 KiB
Go
|
package testing
|
||
|
|
||
|
import (
|
||
|
"testing"
|
||
|
|
||
|
"github.com/stretchr/testify/require"
|
||
|
"github.com/tendermint/tendermint/crypto"
|
||
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||
|
|
||
|
"github.com/cosmos/cosmos-sdk/std"
|
||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||
|
solomachinetypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/solomachine/types"
|
||
|
)
|
||
|
|
||
|
// Solomachine is a testing helper used to simulate a counterparty
|
||
|
// solo machine client.
|
||
|
type Solomachine struct {
|
||
|
t *testing.T
|
||
|
|
||
|
ClientID string
|
||
|
PrivateKey crypto.PrivKey
|
||
|
PublicKey crypto.PubKey
|
||
|
Sequence uint64
|
||
|
Time uint64
|
||
|
}
|
||
|
|
||
|
// NewSolomachine returns a new solomachine instance with a generated private/public
|
||
|
// key pair and a sequence starting at 1.
|
||
|
func NewSolomachine(t *testing.T, clientID string) *Solomachine {
|
||
|
privKey := ed25519.GenPrivKey()
|
||
|
|
||
|
return &Solomachine{
|
||
|
t: t,
|
||
|
ClientID: clientID,
|
||
|
PrivateKey: privKey,
|
||
|
PublicKey: privKey.PubKey(),
|
||
|
Sequence: 1,
|
||
|
Time: 10,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (solo *Solomachine) ClientState() *solomachinetypes.ClientState {
|
||
|
return solomachinetypes.NewClientState(solo.ConsensusState())
|
||
|
}
|
||
|
|
||
|
func (solo *Solomachine) ConsensusState() *solomachinetypes.ConsensusState {
|
||
|
publicKey, err := std.DefaultPublicKeyCodec{}.Encode(solo.PublicKey)
|
||
|
require.NoError(solo.t, err)
|
||
|
|
||
|
return &solomachinetypes.ConsensusState{
|
||
|
Sequence: solo.Sequence,
|
||
|
PublicKey: publicKey,
|
||
|
Timestamp: solo.Time,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// CreateHeader generates a new private/public key pair and creates the
|
||
|
// necessary signature to construct a valid solo machine header.
|
||
|
func (solo *Solomachine) CreateHeader() solomachinetypes.Header {
|
||
|
// generate new private key and signature for header
|
||
|
newPrivKey := ed25519.GenPrivKey()
|
||
|
data := append(sdk.Uint64ToBigEndian(solo.Sequence), newPrivKey.PubKey().Bytes()...)
|
||
|
signature, err := solo.PrivateKey.Sign(data)
|
||
|
require.NoError(solo.t, err)
|
||
|
|
||
|
publicKey, err := std.DefaultPublicKeyCodec{}.Encode(newPrivKey.PubKey())
|
||
|
require.NoError(solo.t, err)
|
||
|
|
||
|
header := solomachinetypes.Header{
|
||
|
Sequence: solo.Sequence,
|
||
|
Signature: signature,
|
||
|
NewPublicKey: publicKey,
|
||
|
}
|
||
|
|
||
|
// assumes successful header update
|
||
|
solo.Sequence++
|
||
|
solo.PrivateKey = newPrivKey
|
||
|
solo.PublicKey = newPrivKey.PubKey()
|
||
|
|
||
|
return header
|
||
|
}
|
||
|
|
||
|
// CreateEvidence constructs testing evidence for the solo machine client
|
||
|
// by signing over two different data bytes at the same sequence.
|
||
|
func (solo *Solomachine) CreateEvidence() solomachinetypes.Evidence {
|
||
|
dataOne := []byte("DATA ONE")
|
||
|
dataTwo := []byte("DATA TWO")
|
||
|
|
||
|
sig, err := solo.PrivateKey.Sign(append(sdk.Uint64ToBigEndian(solo.Sequence), dataOne...))
|
||
|
require.NoError(solo.t, err)
|
||
|
|
||
|
signatureOne := solomachinetypes.SignatureAndData{
|
||
|
Signature: sig,
|
||
|
Data: dataOne,
|
||
|
}
|
||
|
|
||
|
sig, err = solo.PrivateKey.Sign(append(sdk.Uint64ToBigEndian(solo.Sequence), dataTwo...))
|
||
|
require.NoError(solo.t, err)
|
||
|
|
||
|
signatureTwo := solomachinetypes.SignatureAndData{
|
||
|
Signature: sig,
|
||
|
Data: dataTwo,
|
||
|
}
|
||
|
|
||
|
return solomachinetypes.Evidence{
|
||
|
ClientId: solo.ClientID,
|
||
|
Sequence: solo.Sequence,
|
||
|
SignatureOne: &signatureOne,
|
||
|
SignatureTwo: &signatureTwo,
|
||
|
}
|
||
|
}
|