cosmos-sdk/x/ibc/testing/solomachine.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,
}
}