Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(appchain): load subscriber genesis, ibc #176

Closed
wants to merge 52 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
53177cf
feat(appchain): scaffold coordinator
MaxMustermann2 Aug 25, 2024
8ee1253
feat(appchain): scaffold subscriber
MaxMustermann2 Aug 25, 2024
a1158d5
feat(epochs): create number + id structure
MaxMustermann2 Aug 26, 2024
7c1922a
feat(appchain): add coordinator params
MaxMustermann2 Aug 26, 2024
f1bca4d
fix(epochs): invalidate negative duration
MaxMustermann2 Aug 27, 2024
9f9e994
fix(avs): stateful validation of staking assets
MaxMustermann2 Aug 27, 2024
0e1cd06
refactor(dogfood): carve `sortByPower` out
MaxMustermann2 Aug 27, 2024
9073b71
fix(dogfood): avoid duplicate validation
MaxMustermann2 Aug 27, 2024
e06c529
fix(dogfood): replace with max unbonding duration
MaxMustermann2 Aug 27, 2024
04e0d67
doc(app): add comment about slashing frac storage
MaxMustermann2 Aug 27, 2024
2f594b7
feat(appchain): allow sub chain creation
MaxMustermann2 Aug 27, 2024
4bd8948
chore(lint)
MaxMustermann2 Aug 31, 2024
13e6a72
Merge `develop`
MaxMustermann2 Aug 31, 2024
571c65e
fix(test): make avs test pass
MaxMustermann2 Aug 31, 2024
6f4cfa0
fix(appchain): remove superfluous test
MaxMustermann2 Aug 31, 2024
19ce74a
fix(epochs): update expected test message
MaxMustermann2 Aug 31, 2024
0a0688c
chore(lint)
MaxMustermann2 Aug 31, 2024
6cb92fc
chore(lint): proto lint
MaxMustermann2 Aug 31, 2024
ca8b2ee
chore: run proto gen
MaxMustermann2 Aug 31, 2024
cfba037
fix(appchain): remove floating point arithmetic
MaxMustermann2 Aug 31, 2024
013f938
fix(appchain): remove wrong comment
MaxMustermann2 Aug 31, 2024
dc7915d
doc(appchain): add comment about params expect
MaxMustermann2 Aug 31, 2024
607e12e
fix(appchain): remove superfluous fmt
MaxMustermann2 Aug 31, 2024
4a275d3
feat(appchain): report invalid json
MaxMustermann2 Aug 31, 2024
e9d8fc0
fix(utils): remove SliceStable and use Slice
MaxMustermann2 Aug 31, 2024
3be6882
doc(appchain): add more logging
MaxMustermann2 Aug 31, 2024
4401e3f
chore(lint)
MaxMustermann2 Aug 31, 2024
47714fc
fix(ci): pin the golang lint version
MaxMustermann2 Aug 31, 2024
2904a40
chore(lint): remove unused timestamp proto
MaxMustermann2 Aug 31, 2024
8d0db6c
refactor(dogfood,operator): carve out wrapped key
MaxMustermann2 Sep 1, 2024
079953e
feat(subscriber): load genesis validators
MaxMustermann2 Sep 1, 2024
eb18ccb
fix: unnecessary parent code import
MaxMustermann2 Sep 1, 2024
f99dbca
fix: remove double proto warning
MaxMustermann2 Sep 1, 2024
79833d5
refactor(operator): carve out AppendMany
MaxMustermann2 Sep 2, 2024
b12b362
feat(appchain): load subscriber genesis, ibc
MaxMustermann2 Sep 2, 2024
e2b541d
part 2 commit including handling
MaxMustermann2 Sep 9, 2024
0d235bb
Merge develop
MaxMustermann2 Sep 9, 2024
9b21e48
fix build
MaxMustermann2 Sep 9, 2024
a8a8d1f
chore: lint the proto file
MaxMustermann2 Sep 9, 2024
05cee6d
attempt to fix tests
MaxMustermann2 Sep 9, 2024
bd43d6a
fix retry
MaxMustermann2 Sep 9, 2024
f080f54
Merge develop
MaxMustermann2 Sep 9, 2024
5acf528
Fix tests
MaxMustermann2 Sep 9, 2024
00c8707
chore: fix lint by removing duplicated imports
MaxMustermann2 Sep 9, 2024
5438d85
chore: proto lint
MaxMustermann2 Sep 9, 2024
7b7058a
Merge branch 'develop' into appchains-pt2
MaxMustermann2 Oct 13, 2024
985e606
fix: respond to AI comments
MaxMustermann2 Oct 13, 2024
b52b87a
chore(appchain): golang lint
MaxMustermann2 Oct 13, 2024
dd499d1
respond to more AI comments
MaxMustermann2 Oct 13, 2024
cfca848
refactor: rename function param for clarity
MaxMustermann2 Oct 28, 2024
0ca361d
refactor: rename object for clarity
MaxMustermann2 Oct 28, 2024
f9554f2
Merge `develop`
MaxMustermann2 Oct 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions precompiles/avs/avs_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package avs_test

import (
"math/big"
"time"

"cosmossdk.io/math"
assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types"
avskeeper "github.com/ExocoreNetwork/exocore/x/avs/keeper"
"github.com/ExocoreNetwork/exocore/x/avs/types"
"math/big"
"time"

sdkmath "cosmossdk.io/math"
operatorKeeper "github.com/ExocoreNetwork/exocore/x/operator/keeper"
Expand Down
4 changes: 2 additions & 2 deletions proto/exocore/appchain/common/v1/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ message SubscriberParams {
// the rewards from the subscriber to the coordinator. It is used in the event
// that a channel between coordinator and subscriber exists prior to the
// provision of security from Exocore to the appchain. Until a changeover
// process is implemented, it is currently unused. (TODO). The advantage
// process is implemented, it is currently unused (TODO). The advantage
// of reusing a channel that was already in place is that the coin denomination
// which contains a hash of the channel name will remain unchanged.
string distribution_transmission_channel = 2;
Expand Down Expand Up @@ -101,7 +101,7 @@ message CoordinatorInfo {
ibc.lightclients.tendermint.v1.ClientState client_state = 1;
// consensus_state is the consensus state of the coordinator chain.
ibc.lightclients.tendermint.v1.ConsensusState consensus_state = 2;
// initial_val_set is the initial validator set of the coordinator chain.
// initial_val_set is the initial validator set of the subscriber chain.
repeated .tendermint.abci.ValidatorUpdate initial_val_set = 3
[ (gogoproto.nullable) = false ];
}
87 changes: 87 additions & 0 deletions proto/exocore/appchain/common/v1/wire.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
syntax = "proto3";

package exocore.appchain.common.v1;

import "cosmos/staking/v1beta1/staking.proto";
import "gogoproto/gogo.proto";
import "tendermint/abci/types.proto";

option go_package = "github.com/ExocoreNetwork/exocore/x/appchain/common/types";

// This file containts all of the information that is sent over the wire by either
// the coordinator or each of the subcribers.

message HandshakeMetadata {
// coordinator_fee_pool_addr is the address on the coordinator to which the
// subscriber chain will send the fees proportionally and periodically.
string coordinator_fee_pool_addr = 1;
// version is the version of the appchain protocol
string version = 2;
}

// SlashPacketData is sent from the subscriber chain to the coordinator chain
// to request the slashing of a validator as a result of an infraction committed
// on the subscriber chain.
message SlashPacketData {
// validator is the validator to be slashed
tendermint.abci.Validator validator = 1 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"validator\""
];
// valset_update_id is the id of the validator set change during which
// the infraction was committed
uint64 valset_update_id = 2 [ (gogoproto.customname) = "ValsetUpdateID" ];
// infraction refers to the type of infraction committed
cosmos.staking.v1beta1.Infraction infraction = 3;
}

// VscMaturedPacketData is sent from the subscriber chain to the coordinator chain
// to indicate that a VSC has matured and unbondings associated with that VSC
// can now be released.
message VscMaturedPacketData {
// valset_update_id is the id of the validator set change to mature.
uint64 valset_update_id = 1 [ (gogoproto.customname) = "ValsetUpdateID" ];
}

// SubscriberPacketData is the enum to identify the type of packet sent.
enum SubscriberPacketDataType {
option (gogoproto.goproto_enum_prefix) = false;
// SUBSCRIBER_PACKET_DATA_TYPE_UNSPECIFIED is the default value
SUBSCRIBER_PACKET_DATA_TYPE_UNSPECIFIED = 0 [ (gogoproto.enumvalue_customname) = "UnspecifiedPacket" ];
// SUBSCRIBER_PACKET_DATA_TYPE_SLASH is the type of packet sent when a subscriber
// chain wants to request the slashing of a validator on the coordinator chain.
SUBSCRIBER_PACKET_DATA_TYPE_SLASH = 1 [ (gogoproto.enumvalue_customname) = "SlashPacket" ];
// SUBSCRIBER_PACKET_DATA_TYPE_VSC_MATURED is the type of packet sent when a subscriber
// chain wants to indicate that a VSC has matured and unbondings associated with
// that VSC can now be released.
SUBSCRIBER_PACKET_DATA_TYPE_VSC_MATURED = 2 [ (gogoproto.enumvalue_customname) = "VscMaturedPacket" ];
}

// SubscriberPacketData is a wrapped message that contains the type of packet
// and the data associated with that packet.
message SubscriberPacketData {
// type is the type of packet sent
SubscriberPacketDataType type = 1;
// data is the data associated with the packet
oneof data {
// slash_packet_data is the data associated with a SlashPacket
SlashPacketData slash_packet_data = 2;
// vsc_matured_packet_data is the data associated with a VscMaturedPacket
VscMaturedPacketData vsc_matured_packet_data = 3;
}
}

// ValidatorSetChangePacketData is sent from the coordinator chain to the subscriber chain
// containing the new validator set and the id of the validator set change.
message ValidatorSetChangePacketData {
// validator_updates is the edits to the existing validator set
repeated .tendermint.abci.ValidatorUpdate validator_updates = 1 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"validator_updates\""
];
// valset_update_id is the id of the validator set change
uint64 valset_update_id = 2 [(gogoproto.customname) = "ValsetUpdateID"];
// slash_acks is the list of consensus addresses slashed on the coordinator chain,
// in response to such requests from the subscriber chain.
repeated string slash_acks = 3;
}
5 changes: 5 additions & 0 deletions proto/exocore/appchain/coordinator/v1/coordinator.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ message ChainIDs {
repeated string list = 1;
}

// ConsensusAddresses is a list of consensus addresses.
message ConsensusAddresses {
// list is the list of consensus addresses.
repeated bytes list = 1;
}
26 changes: 25 additions & 1 deletion proto/exocore/appchain/subscriber/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,35 @@ package exocore.appchain.subscriber.v1;

import "exocore/appchain/common/v1/common.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/ExocoreNetwork/exocore/x/appchain/subscriber/types";

// GenesisState is the genesis state for the appchain subscriber module.
message GenesisState {
// Params is the parameters for the appchain subscriber module.
// The first two fields are word-for-word pulled from `common.proto`, to be
// filled by the coordinator module (or an export).
// params is the parameters for the appchain subscriber module.
exocore.appchain.common.v1.SubscriberParams params = 1 [(gogoproto.nullable) = false];
// coordinator is the coordinator information for the subscriber.
exocore.appchain.common.v1.CoordinatorInfo coordinator = 2 [ (gogoproto.nullable) = false ];
// Below are the IBC parameters
// coordinator_client_id is the client id of the coordinator chain.
string coordinator_client_id = 3 [ (gogoproto.customname) = "CoordinatorClientID" ];
// coordinator_channel_id is the channel id of the coordinator chain.
string coordinator_channel_id = 4 [ (gogoproto.customname) = "CoordinatorChannelID" ];
// operational parameters that are to be exported can go here.
}

// MaturingVSCPacket represents a vsc packet that is maturing internal to the
// subscriber module, where it has not yet relayed a VSCMatured packet back.
// While it is technically feasible to store this just as a key in the state,
// keeping it as a separate type allows exporting the genesis data.
// The key used is prefix + time + vscId.
message MaturingVSCPacket {
// vsc_id is the id of the VSC that is maturing.
uint64 vsc_id = 1 [ (gogoproto.customname) = "ValidatorSetChangeID" ];
// maturity_time is the time at which the VSC will mature.
google.protobuf.Timestamp maturity_time = 2
[ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ];
}
26 changes: 26 additions & 0 deletions proto/exocore/appchain/subscriber/v1/subscriber.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
syntax = "proto3";

package exocore.appchain.subscriber.v1;

import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";

option go_package = "github.com/ExocoreNetwork/exocore/x/appchain/subscriber/types";

// SubscriberChainValidator is a validator structure on the subscriber chain.
// The name is verbose intentionally.
message SubscriberChainValidator {
// address, as derived from the consensus key. No correlation with the operator
// address on Exocore.
bytes cons_address = 1;
// power is the vote power of the validator
int64 power = 2;
// pubkey is the consensus public key of the validator, as a Protobuf Any.
// this type is chosen to match the x/staking/validator type.
google.protobuf.Any pubkey = 3 [
(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey",
(gogoproto.moretags) = "yaml:\"consensus_pubkey\""
];
}

2 changes: 1 addition & 1 deletion testutil/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (suite *BaseTestSuite) SetupWithGenesisValSet(genAccs []authtypes.GenesisAc
suite.Require().NotNil(pubKey)
pubKey2 := testutiltx.GenerateConsensusKey()
suite.Require().NotNil(pubKey2)
chainIDWithoutRevision := avstypes.ChainIDWithoutRevision(utils.DefaultChainID)
chainIDWithoutRevision := utils.ChainIDWithoutRevision(utils.DefaultChainID)
operatorConsKeys := []operatortypes.OperatorConsKeyRecord{
{
OperatorAddress: operator1.String(),
Expand Down
52 changes: 52 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

ibcclienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"

abci "github.com/cometbft/cometbft/abci/types"

"github.com/evmos/evmos/v16/crypto/ethsecp256k1"
"golang.org/x/exp/constraints"
"golang.org/x/xerrors"
Expand Down Expand Up @@ -210,3 +212,53 @@
}
return sortedOperatorAddrs, sortedPubKeys, sortedPowers
}

// AccumulateChanges accumulates the current and new validator updates and returns
// a list of unique validator updates. The list is sorted by power in descending order.
func AccumulateChanges(
currentChanges, newChanges []abci.ValidatorUpdate,
) []abci.ValidatorUpdate {
// get only unique updates
m := make(map[string]abci.ValidatorUpdate)
for _, change := range currentChanges {
m[change.PubKey.String()] = change
}
for _, change := range newChanges {
m[change.PubKey.String()] = change
}

// convert to list
out := make([]abci.ValidatorUpdate, 0, len(m))
for _, update := range m {
out = append(out, update)
}

// The list of tendermint updates should hash the same across all consensus nodes
// that means it is necessary to sort for determinism.
sort.Slice(out, func(i, j int) bool {
if out[i].Power != out[j].Power {
return out[i].Power > out[j].Power
}
return out[i].PubKey.String() > out[j].PubKey.String()
})

return out
}

// AppendMany appends a variable number of byte slices together
func AppendMany(slices ...[]byte) (out []byte) {
for _, slice := range slices {
out = append(out, slice...)
}
return out
}

// ChainIDWithoutRevision returns the chainID without the revision number.
// For example, "exocoretestnet_233-1" returns "exocoretestnet_233".
func ChainIDWithoutRevision(chainID string) string {
if !ibcclienttypes.IsRevisionFormat(chainID) {
return chainID
}
splitStr := strings.Split(chainID, "-")
return splitStr[0]
}
4 changes: 2 additions & 2 deletions x/appchain/common/types/common.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions x/appchain/common/types/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package types

import (
errorsmod "cosmossdk.io/errors"
)

var (
ErrInvalidChannelFlow = errorsmod.Register(
ModuleName, 2,
"invalid message sent to channel end",
)
ErrDuplicateChannel = errorsmod.Register(
ModuleName, 3,
"channel already exists",
)
ErrInvalidVersion = errorsmod.Register(
ModuleName, 4,
"invalid version",
)
ErrInvalidHandshakeMetadata = errorsmod.Register(
ModuleName, 5,
"invalid handshake metadata",
)
ErrChannelNotFound = errorsmod.Register(
ModuleName, 6,
"channel not found",
)
ErrClientNotFound = errorsmod.Register(
ModuleName, 7,
"client not found",
)
ErrInvalidPacketData = errorsmod.Register(
ModuleName, 8,
"invalid packet data (but successfully unmarshalled)",
)
)
9 changes: 8 additions & 1 deletion x/appchain/common/types/events.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package types

const (
AttributeChainID = "chain_id"
AttributeChainID = "chain_id"
AttributeKeyAckSuccess = "success"
AttributeKeyAck = "acknowledgement"
AttributeKeyAckError = "ack_error"

EventTypeChannelEstablished = "channel_established"
EventTypePacket = "common_packet"
EventTypeTimeout = "common_timeout"
)
Loading
Loading