Integrate go-nitro

- Add nitro server and x/nitro module
    - wire go-nitro p2p through cometbft

- Add distsig server, currently WIP
    - integrate DKG and DSS schemes into ABCI methods

- Remove deprecated features
    - crisis module
    - module invariants

- Update to use newer SDK patterns
    - upgrade sdk to v0.53.x
    - custom address codec
    - expand use of depinject
    - migrate e2e tests to system tests
    - use depinject to set up integration tests
    - change reserved protobuf field name `cerc.registry.v1.Record.type`

- Revise & add documentation
    - TransferCoinsToModuleAccount: clarify function

- Update init.sh script
This commit is contained in:
roysc committed 2025-09-21 11:44:44 +08:00
1 parent a8ebc0aceb
commit 5aa2594073
179 files changed
+15631 -3058

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
package utils
import (
"cosmossdk.io/core/address"
errorsmod "cosmossdk.io/errors"
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/runtime"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"git.vdb.to/cerc-io/laconicd/app/params"
)
type addressCodec struct {
address.Codec
}
func (ac addressCodec) StringToBytes(text string) ([]byte, error) {
bz, err := ac.Codec.StringToBytes(text)
if err != nil {
return nil, err
}
if len(bz) != 20 && len(bz) != 32 {
return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownAddress,
"address length must be 20 or 32 bz, got %d", len(bz))
}
return bz, nil
}
func NewAddressCodec() address.Codec {
return addressCodec{
Codec: addresscodec.NewBech32Codec(params.Bech32PrefixAccAddr),
}
}
func NewValidatorAddressCodec() runtime.ValidatorAddressCodec {
return addressCodec{
Codec: addresscodec.NewBech32Codec(params.Bech32PrefixValAddr),
}
}
func NewConsensusAddressCodec() runtime.ConsensusAddressCodec {
return addressCodec{
Codec: addresscodec.NewBech32Codec(params.Bech32PrefixConsAddr),
}
}
func MustBytesToString(ac address.Codec, bz []byte) string {
str, err := ac.BytesToString(bz)
if err != nil {
panic(err)
}
return str
}
+18
View File
@@ -0,0 +1,18 @@
package utils
import (
"context"
"errors"
"fmt"
)
func GetFromContext[T any](ctx context.Context, key string) (*T, error) {
if v := ctx.Value(key); v != nil {
val, ok := v.(*T)
if !ok {
return nil, fmt.Errorf("context value of wrong type; expected %T, got %T", new(T), v)
}
return val, nil
}
return nil, errors.New("key not found in context: " + key)
}
+25 -15
View File
@@ -1,29 +1,39 @@
package utils
import (
"context"
"fmt"
"cosmossdk.io/core/gas"
"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func CtxWithCustomKVGasConfig(ctx *sdk.Context) *sdk.Context {
updatedCtx := ctx.WithKVGasConfig(storetypes.GasConfig{
HasCost: 0,
DeleteCost: 0,
ReadCostFlat: 0,
ReadCostPerByte: 0,
WriteCostFlat: 0,
WriteCostPerByte: 0,
IterNextCostFlat: 0,
})
const RefundModuleGasDescriptor = "laconic module gas refund"
return &updatedCtx
// WithCustomGasConfig returns a context with a zero-cost gas config, and a function to log all consumed gas.
//
// Note: as planned in server/v2, the gas meter will not be available on the STF-provided context
// during tx execution, and must be accessed via gas.Service instead. This arg is a placeholder
// to ensure modules using this include the gas service in anticipation of that change.
// https://github.com/cosmos/cosmos-sdk/pull/16310
func WithCustomGasConfig(ctx context.Context, _ gas.Service) (context.Context, func(log.Logger, string)) {
c := sdk.UnwrapSDKContext(ctx)
meter := c.GasMeter()
startGas := meter.GasConsumed()
logGas := func(logger log.Logger, method string) {
endGas := meter.GasConsumed()
meter.RefundGas(endGas-startGas, RefundModuleGasDescriptor)
LogTxGasConsumed(meter, logger, method)
}
// Set a zero-cost gas config on the returned context
return c.WithKVGasConfig(storetypes.GasConfig{}), logGas
}
func LogTxGasConsumed(ctx sdk.Context, logger log.Logger, tx string) {
gasConsumed := ctx.GasMeter().GasConsumed()
logger.Info("tx executed", "method", tx, "gas_consumed", fmt.Sprintf("%d", gasConsumed))
func LogTxGasConsumed(gm gas.Meter, logger log.Logger, method string) {
gasConsumed := gm.GasConsumed()
logger.Info("tx executed", "method", method, "gas_consumed", fmt.Sprintf("%d", gasConsumed))
}
+79
View File
@@ -0,0 +1,79 @@
package utils
import (
"cosmossdk.io/core/address"
sdkerrors "cosmossdk.io/errors"
cmtcrypto "github.com/cometbft/cometbft/crypto"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdkcrypto "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// cosmos-sdk crypto/keyring/record.go:138
func extractPrivKeyFromLocal(rl *keyring.Record_Local) (cmtcrypto.PrivKey, error) {
if rl.PrivKey == nil {
return nil, keyring.ErrPrivKeyNotAvailable
}
priv, ok := rl.PrivKey.GetCachedValue().(sdkcrypto.PrivKey)
if !ok {
return nil, sdkerrors.Wrap(keyring.ErrCastAny, "PrivKey")
}
return &PrivKey{priv}, nil
}
func ExtractPrivateKey(r *keyring.Record) (cmtcrypto.PrivKey, error) {
local := r.GetLocal()
if local == nil {
return nil, keyring.ErrPrivKeyExtr
}
return extractPrivKeyFromLocal(local)
}
func ExtractPrivateKeyByUid(kr keyring.Keyring, uid string) (cmtcrypto.PrivKey, error) {
r, err := kr.Key(uid)
if err != nil {
return nil, err
}
return ExtractPrivateKey(r)
}
// GetKeyRecord tries to get a key by either address or uid
func GetKeyRecord(kr keyring.Keyring, from string, ac address.Codec) (*keyring.Record, error) {
var k *keyring.Record
addr, err := ac.StringToBytes(from)
if err == nil {
k, err = kr.KeyByAddress(sdk.AccAddress(addr))
if err != nil {
return nil, err
}
} else {
k, err = kr.Key(from)
if err != nil {
return nil, err
}
}
return k, nil
}
// PrivKey wraps the SDK PrivKey type to satisfy cometbft/crypto.PrivKey
type PrivKey struct{ sdkcrypto.PrivKey }
func (k PrivKey) PubKey() cmtcrypto.PubKey { return PubKey{k.PrivKey.PubKey()} }
func (k PrivKey) Equals(other cmtcrypto.PrivKey) bool {
if otherPk, ok := other.(*PrivKey); ok {
return k.PrivKey.Equals(otherPk.PrivKey)
}
return false
}
// PubKey wraps the SDK PubKey type to satisfy cometbft/crypto.PubKey
type PubKey struct{ sdkcrypto.PubKey }
func (k PubKey) Equals(other cmtcrypto.PubKey) bool {
if otherPk, ok := other.(*PubKey); ok {
return k.PubKey.Equals(otherPk.PubKey)
}
return false
}
+38
View File
@@ -0,0 +1,38 @@
package utils
import (
"cosmossdk.io/core/address"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/types"
sdk "github.com/cosmos/cosmos-sdk/types"
addresstypes "github.com/cosmos/cosmos-sdk/types/address"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
)
// AddressOrModuleAddress returns with this precedence:
// - the preferred address if it is valid, or
// - a module address with the preferred name, or
// - a module address with the alt name
func AddressOrModuleAddress(preferred, alt string) types.AccAddress {
if preferred != "" {
addrCodec := NewAddressCodec()
if addr, err := addrCodec.StringToBytes(preferred); err == nil {
return addr
}
return addresstypes.Module(preferred)
}
return addresstypes.Module(alt)
}
func CheckAuthorityAddress(ac address.Codec, expected sdk.AccAddress, msgaddr string) error {
authority, err := ac.StringToBytes(msgaddr)
if err != nil {
return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, msgaddr)
}
if !expected.Equals(types.AccAddress(authority)) {
return errorsmod.Wrapf(govtypes.ErrInvalidSigner,
"invalid authority; expected %s, got %s", MustBytesToString(ac, expected), msgaddr)
}
return nil
}
+20 -3
View File
@@ -2,17 +2,34 @@ package utils
import (
"github.com/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/statechannels/go-nitro/crypto"
)
func DecodeEthereumAddress(message []byte, sig string) (string, error) {
func DecodeEthereumAddress(message []byte, sig string) (common.Address, error) {
if len(sig) > 2 && sig[:2] == "0x" {
sig = sig[2:]
}
signature := crypto.SplitSignature(common.Hex2Bytes(sig))
ethereumAddress, err := crypto.RecoverEthereumMessageSigner(message, signature)
return crypto.RecoverEthMessageSignerAddress(message, signature)
}
return ethereumAddress.String(), err
// TODO: use compressed pubkey encoding?
func DecodeEthereumPubKey(message []byte, sig string) ([]byte, error) {
if len(sig) > 2 && sig[:2] == "0x" {
sig = sig[2:]
}
signature := crypto.SplitSignature(common.Hex2Bytes(sig))
return crypto.RecoverEthMessageSignerPubKey(message, signature)
}
func EthAddressFromPubKey(pubkey []byte) (common.Address, error) {
ecdsaPubKey, err := ethcrypto.UnmarshalPubkey(pubkey)
if err != nil {
return common.Address{}, err
}
return ethcrypto.PubkeyToAddress(*ecdsaPubKey), nil
}