Skip to content

Commit

Permalink
Merge pull request #3833 from oasisprotocol/ptrus/feature/consensus-r…
Browse files Browse the repository at this point in the history
…untime-interop

Runtime consensus state interoperability tests
  • Loading branch information
ptrus authored Apr 16, 2021
2 parents 209a89c + 42d73ea commit d29a78e
Show file tree
Hide file tree
Showing 12 changed files with 682 additions and 15 deletions.
1 change: 1 addition & 0 deletions .changelog/3833.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Runtime consensus state interoperability tests
204 changes: 204 additions & 0 deletions go/consensus/tendermint/apps/staking/state/interop/interop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package interop

import (
"context"
"fmt"

"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
stakingState "github.com/oasisprotocol/oasis-core/go/consensus/tendermint/apps/staking/state"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs"
)

var addresses []staking.Address

// Keep this in sync with tests in runtimes/consensus/state/staking.rs.
func InitializeTestStakingState(ctx context.Context, mkvs mkvs.Tree) error {
state := stakingState.NewMutableState(mkvs)

// Populate accounts.
for _, acc := range []struct {
address staking.Address
account *staking.Account
}{
{
addresses[0],
&staking.Account{
General: staking.GeneralAccount{
Balance: *quantity.NewFromUint64(23),
Nonce: 13,
},
Escrow: staking.EscrowAccount{
Active: staking.SharePool{
Balance: *quantity.NewFromUint64(100),
TotalShares: *quantity.NewFromUint64(10),
},
Debonding: staking.SharePool{
Balance: *quantity.NewFromUint64(5),
TotalShares: *quantity.NewFromUint64(5),
},
},
},
},
{
addresses[1],
&staking.Account{
General: staking.GeneralAccount{
Balance: *quantity.NewFromUint64(23),
Nonce: 1,
},
Escrow: staking.EscrowAccount{
Active: staking.SharePool{
Balance: *quantity.NewFromUint64(500),
TotalShares: *quantity.NewFromUint64(5),
},
},
},
},
{
addresses[2],
&staking.Account{
General: staking.GeneralAccount{
Balance: *quantity.NewFromUint64(113),
Nonce: 17,
},
Escrow: staking.EscrowAccount{
Active: staking.SharePool{
Balance: *quantity.NewFromUint64(400),
TotalShares: *quantity.NewFromUint64(35),
},
},
},
},
} {
if err := state.SetAccount(ctx, acc.address, acc.account); err != nil {
return fmt.Errorf("setting account: %w", err)
}
}

// Initialize delegations.
for _, del := range []struct {
from staking.Address
to staking.Address
d *staking.Delegation
}{
{
from: addresses[0],
to: addresses[0],
d: &staking.Delegation{
Shares: *quantity.NewFromUint64(5),
},
},
{
from: addresses[0],
to: addresses[2],
d: &staking.Delegation{
Shares: *quantity.NewFromUint64(20),
},
},
{
from: addresses[1],
to: addresses[0],
d: &staking.Delegation{
Shares: *quantity.NewFromUint64(5),
},
},
{
from: addresses[1],
to: addresses[2],
d: &staking.Delegation{
Shares: *quantity.NewFromUint64(6),
},
},
{
from: addresses[2],
to: addresses[1],
d: &staking.Delegation{
Shares: *quantity.NewFromUint64(5),
},
},
{
from: addresses[2],
to: addresses[2],
d: &staking.Delegation{
Shares: *quantity.NewFromUint64(10),
},
},
} {
if err := state.SetDelegation(ctx, del.from, del.to, del.d); err != nil {
return err
}
}

// Initialize debonding delegations.
for _, deb := range []struct {
from staking.Address
to staking.Address
d *staking.DebondingDelegation
}{
{
from: addresses[0],
to: addresses[0],
d: &staking.DebondingDelegation{
Shares: *quantity.NewFromUint64(1),
DebondEndTime: 33,
},
},
{
from: addresses[1],
to: addresses[0],
d: &staking.DebondingDelegation{
Shares: *quantity.NewFromUint64(1),
DebondEndTime: 15,
},
},
{
from: addresses[1],
to: addresses[0],
d: &staking.DebondingDelegation{
Shares: *quantity.NewFromUint64(1),
DebondEndTime: 21,
},
},
{
from: addresses[2],
to: addresses[0],
d: &staking.DebondingDelegation{
Shares: *quantity.NewFromUint64(2),
DebondEndTime: 100,
},
},
} {
if err := state.SetDebondingDelegation(ctx, deb.from, deb.to, deb.d.DebondEndTime, deb.d); err != nil {
return err
}
}

// Initialize balances.
if err := state.SetTotalSupply(ctx, quantity.NewFromUint64(10000)); err != nil {
return err
}
if err := state.SetCommonPool(ctx, quantity.NewFromUint64(1000)); err != nil {
return err
}
if err := state.SetLastBlockFees(ctx, quantity.NewFromUint64(33)); err != nil {
return err
}
if err := state.SetGovernanceDeposits(ctx, quantity.NewFromUint64(12)); err != nil {
return err
}

return nil
}

func init() {
pk := signature.NewPublicKey("7e57baaad01fffffffffffffffffffffffffffffffffffffffffffffffffffff")
pk2 := signature.NewPublicKey("7e57baaad02fffffffffffffffffffffffffffffffffffffffffffffffffffff")
pk3 := signature.NewPublicKey("7e57baaad03fffffffffffffffffffffffffffffffffffffffffffffffffffff")
addresses = append(addresses,
staking.NewAddress(pk),
staking.NewAddress(pk2),
staking.NewAddress(pk3),
)
}
44 changes: 44 additions & 0 deletions go/storage/mkvs/interop/cmd/protocol_server.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"context"
"fmt"
"io"
"os"
Expand All @@ -16,13 +17,19 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/logging"
genesisTestHelpers "github.com/oasisprotocol/oasis-core/go/genesis/tests"
"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/background"
"github.com/oasisprotocol/oasis-core/go/storage/api"
storage "github.com/oasisprotocol/oasis-core/go/storage/api"
"github.com/oasisprotocol/oasis-core/go/storage/database"
badgerNodedb "github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/badger"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs/interop/fixtures"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs/node"
)

const (
cfgServerSocket = "socket"
cfgServerDataDir = "datadir"

cfgServerFixture = "fixture"
)

var (
Expand Down Expand Up @@ -96,6 +103,42 @@ func doProtoServer(cmd *cobra.Command, args []string) {
InsecureSkipChecks: false,
MaxCacheSize: 16 * 1024 * 1024,
}

if fixtureName := viper.GetString(cfgServerFixture); fixtureName != "" {
ctx := context.Background()
ndbCfg := storageCfg.ToNodeDB()
var ndb api.NodeDB
ndb, err = badgerNodedb.New(ndbCfg)
if err != nil {
logger.Error("failed to initialize node db",
"err", err,
)
return
}
var fixture fixtures.Fixture
fixture, err = fixtures.GetFixture(fixtureName)
if err != nil {
logger.Error("failed getting fixture",
"err", err,
"fixture", fixture.Name(),
)
return
}
var root *node.Root
root, err = fixture.Populate(ctx, ndb)
if err != nil {
logger.Error("failed to populate fixture",
"err", err,
"fixture", fixture.Name(),
)
return
}

fmt.Printf("Fixture: %s, populated root hash: %s\n", fixtureName, root.Hash)

ndb.Close()
}

backend, err := database.New(&storageCfg)
if err != nil {
logger.Error("failed to initialize storage backend",
Expand Down Expand Up @@ -130,5 +173,6 @@ func RegisterProtoServer(parentCmd *cobra.Command) {
func init() {
protoServerFlags.String(cfgServerSocket, "storage.sock", "path to storage protocol server socket")
protoServerFlags.String(cfgServerDataDir, "", "path to data directory")
protoServerFlags.String(cfgServerFixture, "", "fixture for initializing initial state")
_ = viper.BindPFlags(protoServerFlags)
}
50 changes: 50 additions & 0 deletions go/storage/mkvs/interop/fixtures/consensus_mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package fixtures

import (
"context"
"fmt"

"github.com/oasisprotocol/oasis-core/go/common"
stakingInterop "github.com/oasisprotocol/oasis-core/go/consensus/tendermint/apps/staking/state/interop"
storage "github.com/oasisprotocol/oasis-core/go/storage/api"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs"
db "github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/api"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs/node"
)

const consensusMockName = "consensus_mock"

var consensusMockFixture = consensusMock{}

type consensusMock struct {
}

func (c *consensusMock) Name() string {
return consensusMockName
}

func (c *consensusMock) Populate(ctx context.Context, ndb db.NodeDB) (*node.Root, error) {
var err error
testRoot := storage.Root{
Type: storage.RootTypeState,
Version: 1,
}

mkvsTree := mkvs.New(nil, ndb, node.RootTypeState, mkvs.WithoutWriteLog())
if err = stakingInterop.InitializeTestStakingState(ctx, mkvsTree); err != nil {
return nil, fmt.Errorf("consensus-mock: failed to initialize state: %w", err)
}
_, testRoot.Hash, err = mkvsTree.Commit(ctx, common.Namespace{}, 1)
if err != nil {
return nil, fmt.Errorf("consensus-mock: failed to committ tree: %w", err)
}
if err = ndb.Finalize(ctx, []node.Root{testRoot}); err != nil {
return nil, fmt.Errorf("consensus-mock: failed to finalize test root: %w", err)
}

return &testRoot, nil
}

func init() {
Register(&consensusMockFixture)
}
45 changes: 45 additions & 0 deletions go/storage/mkvs/interop/fixtures/fixture.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package fixtures

import (
"context"
"fmt"
"sync"

db "github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/api"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs/node"
)

var (
registeredFixtures sync.Map

// ErrMissingFixture is the error returned when getting a nonexisting fixture.
ErrMissingFixture = fmt.Errorf("fixture does not exist")
)

// Fixture is a protocol server fixture.
type Fixture interface {
// Name is the name of the fixture.
Name() string

// Populate populates the db with the fixture.
Populate(context.Context, db.NodeDB) (*node.Root, error)
}

// Register registers a new fixture.
func Register(fixture Fixture) {
name := fixture.Name()
if _, isRegistered := registeredFixtures.Load(name); isRegistered {
panic(fmt.Errorf("fixture already registered: %s", name))
}
registeredFixtures.Store(name, fixture)
}

// GetFixture returns a registered fixture by name.
func GetFixture(name string) (Fixture, error) {
h, exists := registeredFixtures.Load(name)
if !exists {
return nil, ErrMissingFixture
}

return h.(Fixture), nil
}
Loading

0 comments on commit d29a78e

Please sign in to comment.