Skip to content

Commit

Permalink
finality: sudo message for BeginBlock (#8)
Browse files Browse the repository at this point in the history
Closes #2 

This PR provides sudo message `BeginBlock` for Babylon contracts. The
sudo message will be sent to BTC staking contract upon each
`BeginBlock`.

To test, run `make test-e2e`. Note that the wasm files are generated on
babylonchain/babylon-contract#123
  • Loading branch information
SebastianElvis authored Jun 10, 2024
1 parent 7960ef0 commit 22717cd
Show file tree
Hide file tree
Showing 24 changed files with 868 additions and 122 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ vendor/

# Go workspace file
coverage.txt

demo/build/
37 changes: 36 additions & 1 deletion docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
- [Query](#babylonchain.babylon.v1beta1.Query)

- [babylonchain/babylon/v1beta1/tx.proto](#babylonchain/babylon/v1beta1/tx.proto)
- [MsgUpdateParams](#babylonchain.babylon.v1beta1.MsgUpdateParams)
- [MsgUpdateParamsResponse](#babylonchain.babylon.v1beta1.MsgUpdateParamsResponse)

- [Msg](#babylonchain.babylon.v1beta1.Msg)

- [Scalar Value Types](#scalar-value-types)
Expand All @@ -38,7 +41,9 @@ Params defines the parameters for the x/babylon module.

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `max_gas_end_blocker` | [uint32](#uint32) | | MaxGasEndBlocker defines the maximum gas that can be spent in a contract sudo callback |
| `babylon_contract_address` | [string](#string) | | babylon_contract_address is the address of the Babylon contract |
| `btc_staking_contract_address` | [string](#string) | | btc_staking_contract_address is the address of the BTC staking contract |
| `max_gas_begin_blocker` | [uint32](#uint32) | | max_gas_begin_blocker defines the maximum gas that can be spent in a contract sudo callback |



Expand Down Expand Up @@ -144,6 +149,35 @@ Query provides defines the gRPC querier service
## babylonchain/babylon/v1beta1/tx.proto



<a name="babylonchain.babylon.v1beta1.MsgUpdateParams"></a>

### MsgUpdateParams
MsgUpdateParams is the Msg/UpdateParams request type.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `authority` | [string](#string) | | authority is the address that controls the module (defaults to x/gov unless overwritten). |
| `params` | [Params](#babylonchain.babylon.v1beta1.Params) | | params defines the x/auth parameters to update.

NOTE: All parameters must be supplied. |






<a name="babylonchain.babylon.v1beta1.MsgUpdateParamsResponse"></a>

### MsgUpdateParamsResponse
MsgUpdateParamsResponse defines the response structure for executing a
MsgUpdateParams message.





<!-- end messages -->

<!-- end enums -->
Expand All @@ -158,6 +192,7 @@ Msg defines the wasm Msg service.

| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `UpdateParams` | [MsgUpdateParams](#babylonchain.babylon.v1beta1.MsgUpdateParams) | [MsgUpdateParamsResponse](#babylonchain.babylon.v1beta1.MsgUpdateParamsResponse) | UpdateParams defines a (governance) operation for updating the x/auth module parameters. The authority defaults to the x/gov module account. | |

<!-- end services -->

Expand Down
15 changes: 10 additions & 5 deletions proto/babylonchain/babylon/v1beta1/babylon.proto
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
syntax = "proto3";
package babylonchain.babylon.v1beta1;

import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "amino/amino.proto";

option go_package = "github.com/babylonchain/babylon-sdk/x/babylon/types";
option (gogoproto.goproto_getters_all) = false;
option (gogoproto.equal_all) = false;

// Params defines the parameters for the x/babylon module.
message Params {
option (amino.name) = "babylon/Params";
option (gogoproto.equal) = true;

// MaxGasEndBlocker defines the maximum gas that can be spent in a contract
// sudo callback
uint32 max_gas_end_blocker = 3;
// babylon_contract_address is the address of the Babylon contract
string babylon_contract_address = 1
[ (cosmos_proto.scalar) = "cosmos.AddressString" ];
// btc_staking_contract_address is the address of the BTC staking contract
string btc_staking_contract_address = 2
[ (cosmos_proto.scalar) = "cosmos.AddressString" ];
// max_gas_begin_blocker defines the maximum gas that can be spent in a
// contract sudo callback
uint32 max_gas_begin_blocker = 3;
}
28 changes: 27 additions & 1 deletion proto/babylonchain/babylon/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,35 @@ syntax = "proto3";
package babylonchain.babylon.v1beta1;

import "gogoproto/gogo.proto";
import "cosmos/msg/v1/msg.proto";
import "cosmos_proto/cosmos.proto";
import "babylonchain/babylon/v1beta1/babylon.proto";

option go_package = "github.com/babylonchain/babylon-sdk/x/babylon/types";
option (gogoproto.goproto_getters_all) = false;

// Msg defines the wasm Msg service.
service Msg {}
service Msg {
option (cosmos.msg.v1.service) = true;

// UpdateParams defines a (governance) operation for updating the x/auth
// module parameters. The authority defaults to the x/gov module account.
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
}

// MsgUpdateParams is the Msg/UpdateParams request type.
message MsgUpdateParams {
option (cosmos.msg.v1.signer) = "authority";

// authority is the address that controls the module (defaults to x/gov unless
// overwritten).
string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

// params defines the x/auth parameters to update.
//
// NOTE: All parameters must be supplied.
Params params = 2 [ (gogoproto.nullable) = false ];
}
// MsgUpdateParamsResponse defines the response structure for executing a
// MsgUpdateParams message.
message MsgUpdateParamsResponse {}
16 changes: 15 additions & 1 deletion tests/e2e/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
var r = rand.New(rand.NewSource(time.Now().Unix()))

// In the Test function, we create and run the suite
func TestMyTestSuite(t *testing.T) {
func TestBabylonSDKTestSuite(t *testing.T) {
suite.Run(t, new(BabylonSDKTestSuite))
}

Expand Down Expand Up @@ -93,6 +93,14 @@ func (s *BabylonSDKTestSuite) Test1ContractDeployment() {
adminResp, err := s.ConsumerCli.Query(s.ConsumerContract.BTCStaking, Query{"admin": {}})
s.NoError(err)
s.Equal(adminResp["admin"], s.ConsumerCli.GetSender().String())

// update the contract address in parameters (typically this has to be done via gov props)
ctx := s.ConsumerChain.GetContext()
params := s.ConsumerApp.BabylonKeeper.GetParams(ctx)
params.BabylonContractAddress = s.ConsumerContract.Babylon.String()
params.BtcStakingContractAddress = s.ConsumerContract.BTCStaking.String()
err = s.ConsumerApp.BabylonKeeper.SetParams(ctx, params)
s.NoError(err)
}

// TestExample is an example test case
Expand All @@ -114,6 +122,12 @@ func (s *BabylonSDKTestSuite) Test2MockFinalityProvider() {
s.NotEmpty(resp)
}

// TODO: trigger BeginBlock via s.ConsumerChain rather than ConsumerApp
func (s *BabylonSDKTestSuite) Test3BeginBlock() {
err := s.ConsumerApp.BabylonKeeper.BeginBlocker(s.ConsumerChain.GetContext())
s.NoError(err)
}

// TearDownSuite runs once after all the suite's tests have been run
func (s *BabylonSDKTestSuite) TearDownSuite() {
// Cleanup code here
Expand Down
Binary file modified tests/testdata/babylon_contract.wasm
Binary file not shown.
Binary file modified tests/testdata/btc_staking.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/testdata/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9695beb27d6f6433582760374ea6a4e4ff58679f
15cbae22a2cfe7c0590b401ae885c68bb1802530
15 changes: 0 additions & 15 deletions x/babylon/abci.go

This file was deleted.

13 changes: 11 additions & 2 deletions x/babylon/contract/out_message.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package contract

import "time"

// SudoMsg is a message sent from the Babylon module to a smart contract
// TODO: implement
type SudoMsg struct {
TestSudoMsg *struct{} `json:"test_sudo_msg,omitempty"`
BeginBlockMsg *BeginBlock `json:"begin_block,omitempty"`
}

type BeginBlock struct {
Height int64 `json:"height"` // Height is the height of the block
HashHex string `json:"hash_hex"` // HashHex is the hash of the block in hex
Time time.Time `json:"time"` // Time is the time of the block
ChainID string `json:"chain_id"` // ChainId is the chain ID of the block
AppHashHex string `json:"app_hash_hex"` // AppHashHex is the app hash of the block in hex
}
22 changes: 22 additions & 0 deletions x/babylon/keeper/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package keeper

import (
"time"

"github.com/babylonchain/babylon-sdk/x/babylon/types"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
)

func (k *Keeper) BeginBlocker(ctx sdk.Context) error {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker)

return k.SendBeginBlockMsg(ctx)
}

// EndBlocker is called after every block
func (k *Keeper) EndBlocker(ctx sdk.Context) ([]abci.ValidatorUpdate, error) {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker)
return []abci.ValidatorUpdate{}, nil
}
1 change: 1 addition & 0 deletions x/babylon/keeper/abci_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package keeper_test
22 changes: 11 additions & 11 deletions x/babylon/keeper/genesis_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package keeper
package keeper_test

import (
"testing"
Expand All @@ -19,15 +19,15 @@ func TestInitGenesis(t *testing.T) {
"custom param, should pass": {
state: types.GenesisState{
Params: types.Params{
MaxGasEndBlocker: 600_000,
MaxGasBeginBlocker: 600_000,
},
},
expErr: false,
},
"custom small value param, should pass": {
state: types.GenesisState{
Params: types.Params{
MaxGasEndBlocker: 10_000,
MaxGasBeginBlocker: 10_000,
},
},
expErr: false,
Expand All @@ -36,25 +36,25 @@ func TestInitGenesis(t *testing.T) {

for name, spec := range specs {
t.Run(name, func(t *testing.T) {
pCtx, keepers := CreateDefaultTestInput(t)
keepers := NewTestKeepers(t)
k := keepers.BabylonKeeper

k.InitGenesis(pCtx, spec.state)
k.InitGenesis(keepers.Ctx, spec.state)

p := k.GetParams(pCtx)
assert.Equal(t, spec.state.Params.MaxGasEndBlocker, p.MaxGasEndBlocker)
p := k.GetParams(keepers.Ctx)
assert.Equal(t, spec.state.Params.MaxGasBeginBlocker, p.MaxGasBeginBlocker)
})
}
}

func TestExportGenesis(t *testing.T) {
pCtx, keepers := CreateDefaultTestInput(t)
keepers := NewTestKeepers(t)
k := keepers.BabylonKeeper
params := types.DefaultParams(sdk.DefaultBondDenom)

err := k.SetParams(pCtx, params)
err := k.SetParams(keepers.Ctx, params)
require.NoError(t, err)

exported := k.ExportGenesis(pCtx)
assert.Equal(t, params.MaxGasEndBlocker, exported.Params.MaxGasEndBlocker)
exported := k.ExportGenesis(keepers.Ctx)
assert.Equal(t, params.MaxGasBeginBlocker, exported.Params.MaxGasBeginBlocker)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package keeper
package keeper_test

import (
"testing"
Expand Down Expand Up @@ -56,6 +56,7 @@ import (
ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper"
"github.com/stretchr/testify/require"

"github.com/babylonchain/babylon-sdk/x/babylon/keeper"
"github.com/babylonchain/babylon-sdk/x/babylon/types"
)

Expand Down Expand Up @@ -98,18 +99,20 @@ func makeEncodingConfig(_ testing.TB) encodingConfig {
}

type TestKeepers struct {
Ctx sdk.Context
StakingKeeper *stakingkeeper.Keeper
SlashingKeeper slashingkeeper.Keeper
BankKeeper bankkeeper.Keeper
StoreKey *storetypes.KVStoreKey
EncodingConfig encodingConfig
BabylonKeeper *Keeper
BabylonKeeper *keeper.Keeper
AccountKeeper authkeeper.AccountKeeper
WasmKeeper *wasmkeeper.Keeper
WasmMsgServer wasmtypes.MsgServer
Faucet *wasmkeeper.TestFaucet
}

func CreateDefaultTestInput(t testing.TB, opts ...Option) (sdk.Context, TestKeepers) {
func NewTestKeepers(t testing.TB, opts ...keeper.Option) TestKeepers {
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db, log.NewTestLogger(t), storemetrics.NewNoOpMetrics())

Expand Down Expand Up @@ -268,8 +271,9 @@ func CreateDefaultTestInput(t testing.TB, opts ...Option) (sdk.Context, TestKeep
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
require.NoError(t, wasmKeeper.SetParams(ctx, wasmtypes.DefaultParams()))
wasmMsgServer := wasmkeeper.NewMsgServerImpl(&wasmKeeper)

msKeeper := NewKeeper(
babylonKeeper := keeper.NewKeeper(
appCodec,
keys[types.StoreKey],
memKeys[types.MemStoreKey],
Expand All @@ -279,18 +283,20 @@ func CreateDefaultTestInput(t testing.TB, opts ...Option) (sdk.Context, TestKeep
authority,
opts...,
)
require.NoError(t, msKeeper.SetParams(ctx, types.DefaultParams(sdk.DefaultBondDenom)))
require.NoError(t, babylonKeeper.SetParams(ctx, types.DefaultParams(sdk.DefaultBondDenom)))

faucet := wasmkeeper.NewTestFaucet(t, ctx, bankKeeper, minttypes.ModuleName, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1_000_000_000_000))
return ctx, TestKeepers{
return TestKeepers{
Ctx: ctx,
AccountKeeper: accountKeeper,
StakingKeeper: stakingKeeper,
SlashingKeeper: slashingKeeper,
BankKeeper: bankKeeper,
StoreKey: keys[types.StoreKey],
EncodingConfig: encConfig,
BabylonKeeper: msKeeper,
BabylonKeeper: babylonKeeper,
WasmKeeper: &wasmKeeper,
WasmMsgServer: wasmMsgServer,
Faucet: faucet,
}
}
Loading

0 comments on commit 22717cd

Please sign in to comment.