77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
package util
|
|
|
|
import (
|
|
"regexp"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk"
|
|
)
|
|
|
|
var (
|
|
// ChainPattern must match any valid chain_id
|
|
ChainPattern = regexp.MustCompile("^[A-Za-z0-9_-]+$")
|
|
)
|
|
|
|
// ChainedTx interface should be implemented by any
|
|
// message to bind it to one chain, with an optional
|
|
// expiration height
|
|
type ChainedTx interface {
|
|
GetChain() ChainData
|
|
}
|
|
|
|
// ChainData is info from the message to bind it to
|
|
// chain and time
|
|
type ChainData struct {
|
|
ChainID string `json:"chain_id"`
|
|
ExpiresAt uint64 `json:"expires_at"`
|
|
}
|
|
|
|
// Chain enforces that this tx was bound to the named chain
|
|
type Chain struct{}
|
|
|
|
var _ sdk.Decorator = Chain{}
|
|
|
|
// CheckTx makes sure we are on the proper chain
|
|
// - fulfills Decorator interface
|
|
func (c Chain) CheckTx(ctx sdk.Context, store sdk.SimpleDB,
|
|
tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) {
|
|
|
|
err = c.checkChainTx(ctx.ChainID(), ctx.BlockHeight(), tx)
|
|
if err != nil {
|
|
return res, err
|
|
}
|
|
return next.CheckTx(ctx, store, tx)
|
|
}
|
|
|
|
// DeliverTx makes sure we are on the proper chain
|
|
// - fulfills Decorator interface
|
|
func (c Chain) DeliverTx(ctx sdk.Context, store sdk.SimpleDB,
|
|
tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) {
|
|
|
|
err = c.checkChainTx(ctx.ChainID(), ctx.BlockHeight(), tx)
|
|
if err != nil {
|
|
return res, err
|
|
}
|
|
return next.DeliverTx(ctx, store, tx)
|
|
}
|
|
|
|
// checkChainTx makes sure the tx is a ChainedTx,
|
|
// it is on the proper chain, and it has not expired.
|
|
func (c Chain) checkChainTx(chainID string, height uint64, tx interface{}) error {
|
|
// make sure it is a chaintx
|
|
ctx, ok := tx.(ChainedTx)
|
|
if !ok {
|
|
return ErrNoChain()
|
|
}
|
|
|
|
data := ctx.GetChain()
|
|
|
|
// compare against state
|
|
if data.ChainID != chainID {
|
|
return ErrWrongChain(data.ChainID)
|
|
}
|
|
if data.ExpiresAt != 0 && data.ExpiresAt <= height {
|
|
return ErrExpired()
|
|
}
|
|
return nil
|
|
}
|