WIP: Nitro integration #65
22
Dockerfile
22
Dockerfile
@ -1,4 +1,4 @@
|
||||
FROM golang:1.21-bullseye AS builder
|
||||
FROM golang:1.23.6-bookworm AS builder
|
||||
|
||||
# Set working directory for the build
|
||||
WORKDIR /go/src/git.vdb.to/cerc-io/laconicd
|
||||
@ -14,21 +14,25 @@ COPY . .
|
||||
RUN make build
|
||||
|
||||
# Final image
|
||||
FROM ubuntu:22.04
|
||||
# DEV golang image
|
||||
FROM golang:1.23.6-bookworm AS base
|
||||
# FROM ubuntu:24.04
|
||||
|
||||
# Install ca-certificates, jq, curl, bash, and other necessary packages
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
jq curl netcat bash \
|
||||
jq yq curl netcat-openbsd bash \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy over binary from the builder
|
||||
COPY --from=builder /go/src/git.vdb.to/cerc-io/laconicd/build/laconicd /usr/bin/laconicd
|
||||
# FROM base
|
||||
|
||||
# Copy over init script from builder
|
||||
COPY --from=builder /go/src/git.vdb.to/cerc-io/laconicd/scripts/init.sh scripts/init.sh
|
||||
# # Copy over binary from the builder
|
||||
# COPY --from=builder /go/src/git.vdb.to/cerc-io/laconicd/build/laconicd /usr/bin/laconicd
|
||||
|
||||
WORKDIR /
|
||||
# # Copy over init script from builder
|
||||
# COPY --from=builder /go/src/git.vdb.to/cerc-io/laconicd/scripts/init.sh scripts/init.sh
|
||||
|
||||
# WORKDIR /
|
||||
|
||||
# Run laconicd by default
|
||||
CMD ["laconicd"]
|
||||
ENTRYPOINT ["laconicd"]
|
||||
|
||||
17
Makefile
17
Makefile
@ -7,12 +7,14 @@ LACONIC_BINARY = laconicd
|
||||
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
||||
COMMIT := $(shell git log -1 --format='%H')
|
||||
|
||||
COSMOS_BUILD_OPTIONS := v2
|
||||
|
||||
# don't override user values
|
||||
ifeq (,$(VERSION))
|
||||
VERSION := $(shell git describe --exact-match 2>/dev/null)
|
||||
# if VERSION is empty, then populate it with branch's name and raw commit hash
|
||||
ifeq (,$(VERSION))
|
||||
VERSION := $(BRANCH)-$(COMMIT)
|
||||
VERSION := $(BRANCH)-$(COMMIT)
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -31,7 +33,7 @@ BUILDDIR ?= $(CURDIR)/build
|
||||
###########
|
||||
|
||||
go.sum: go.mod
|
||||
echo "Ensure dependencies have not been modified ..." >&2
|
||||
@echo "Ensure dependencies have not been modified ..." >&2
|
||||
go mod verify
|
||||
go mod tidy
|
||||
|
||||
@ -42,7 +44,7 @@ build-linux:
|
||||
GOOS=linux GOARCH=amd64 LEDGER_ENABLED=false $(MAKE) build
|
||||
|
||||
$(BUILD_TARGETS): go.sum $(BUILDDIR)/
|
||||
@echo "--> installing laconicd"
|
||||
@echo "--> $@ing laconicd"
|
||||
go $@ $(BUILD_FLAGS) $(BUILD_ARGS) ./...
|
||||
|
||||
$(BUILDDIR)/:
|
||||
@ -56,9 +58,10 @@ all: install
|
||||
### Protobuf ###
|
||||
##################
|
||||
|
||||
protoVer=0.14.0
|
||||
protoVer=0.15.3
|
||||
protoImageName=ghcr.io/cosmos/proto-builder:$(protoVer)
|
||||
protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
|
||||
protoVolumes=-v $(shell readlink -f ..):/mod
|
||||
protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(protoVolumes) $(protoImageName)
|
||||
|
||||
proto-all: proto-format proto-lint proto-gen
|
||||
|
||||
@ -106,3 +109,7 @@ test-e2e:
|
||||
|
||||
test-unit:
|
||||
go test ./utils/... ./cmd/... -mod=readonly -test.v
|
||||
|
||||
test-system: build
|
||||
test -d ./tests/system/binaries || ln -sf $(BUILDDIR) ./tests/system/binaries
|
||||
go test ./tests/system -test.v -timeout 10m
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/auction/v1/query.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Query_Params_FullMethodName = "/cerc.auction.v1.Query/Params"
|
||||
@ -32,6 +32,8 @@ const (
|
||||
// QueryClient is the client API for Query service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Query defines the gRPC querier interface for the auction module
|
||||
type QueryClient interface {
|
||||
// Params queries auction module params
|
||||
Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
|
||||
@ -60,8 +62,9 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient {
|
||||
}
|
||||
|
||||
func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryParamsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -69,8 +72,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
|
||||
}
|
||||
|
||||
func (c *queryClient) Auctions(ctx context.Context, in *QueryAuctionsRequest, opts ...grpc.CallOption) (*QueryAuctionsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryAuctionsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Auctions_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Auctions_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,8 +82,9 @@ func (c *queryClient) Auctions(ctx context.Context, in *QueryAuctionsRequest, op
|
||||
}
|
||||
|
||||
func (c *queryClient) GetAuction(ctx context.Context, in *QueryGetAuctionRequest, opts ...grpc.CallOption) (*QueryGetAuctionResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetAuctionResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetAuction_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetAuction_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -87,8 +92,9 @@ func (c *queryClient) GetAuction(ctx context.Context, in *QueryGetAuctionRequest
|
||||
}
|
||||
|
||||
func (c *queryClient) GetBid(ctx context.Context, in *QueryGetBidRequest, opts ...grpc.CallOption) (*QueryGetBidResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetBidResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetBid_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetBid_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -96,8 +102,9 @@ func (c *queryClient) GetBid(ctx context.Context, in *QueryGetBidRequest, opts .
|
||||
}
|
||||
|
||||
func (c *queryClient) GetBids(ctx context.Context, in *QueryGetBidsRequest, opts ...grpc.CallOption) (*QueryGetBidsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetBidsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetBids_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetBids_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -105,8 +112,9 @@ func (c *queryClient) GetBids(ctx context.Context, in *QueryGetBidsRequest, opts
|
||||
}
|
||||
|
||||
func (c *queryClient) AuctionsByBidder(ctx context.Context, in *QueryAuctionsByBidderRequest, opts ...grpc.CallOption) (*QueryAuctionsByBidderResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryAuctionsByBidderResponse)
|
||||
err := c.cc.Invoke(ctx, Query_AuctionsByBidder_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_AuctionsByBidder_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -114,8 +122,9 @@ func (c *queryClient) AuctionsByBidder(ctx context.Context, in *QueryAuctionsByB
|
||||
}
|
||||
|
||||
func (c *queryClient) AuctionsByOwner(ctx context.Context, in *QueryAuctionsByOwnerRequest, opts ...grpc.CallOption) (*QueryAuctionsByOwnerResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryAuctionsByOwnerResponse)
|
||||
err := c.cc.Invoke(ctx, Query_AuctionsByOwner_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_AuctionsByOwner_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -123,8 +132,9 @@ func (c *queryClient) AuctionsByOwner(ctx context.Context, in *QueryAuctionsByOw
|
||||
}
|
||||
|
||||
func (c *queryClient) GetAuctionModuleBalance(ctx context.Context, in *QueryGetAuctionModuleBalanceRequest, opts ...grpc.CallOption) (*QueryGetAuctionModuleBalanceResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetAuctionModuleBalanceResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetAuctionModuleBalance_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetAuctionModuleBalance_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -133,7 +143,9 @@ func (c *queryClient) GetAuctionModuleBalance(ctx context.Context, in *QueryGetA
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
// All implementations must embed UnimplementedQueryServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Query defines the gRPC querier interface for the auction module
|
||||
type QueryServer interface {
|
||||
// Params queries auction module params
|
||||
Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
|
||||
@ -154,9 +166,12 @@ type QueryServer interface {
|
||||
mustEmbedUnimplementedQueryServer()
|
||||
}
|
||||
|
||||
// UnimplementedQueryServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedQueryServer struct {
|
||||
}
|
||||
// UnimplementedQueryServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedQueryServer struct{}
|
||||
|
||||
func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
|
||||
@ -183,6 +198,7 @@ func (UnimplementedQueryServer) GetAuctionModuleBalance(context.Context, *QueryG
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAuctionModuleBalance not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {}
|
||||
func (UnimplementedQueryServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeQueryServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to QueryServer will
|
||||
@ -192,6 +208,13 @@ type UnsafeQueryServer interface {
|
||||
}
|
||||
|
||||
func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) {
|
||||
// If the following call pancis, it indicates UnimplementedQueryServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Query_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/auction/v1/tx.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Msg_CreateAuction_FullMethodName = "/cerc.auction.v1.Msg/CreateAuction"
|
||||
@ -29,6 +29,8 @@ const (
|
||||
// MsgClient is the client API for Msg service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Tx defines the gRPC tx interface
|
||||
type MsgClient interface {
|
||||
// CreateAuction is the command for creating an auction
|
||||
CreateAuction(ctx context.Context, in *MsgCreateAuction, opts ...grpc.CallOption) (*MsgCreateAuctionResponse, error)
|
||||
@ -52,8 +54,9 @@ func NewMsgClient(cc grpc.ClientConnInterface) MsgClient {
|
||||
}
|
||||
|
||||
func (c *msgClient) CreateAuction(ctx context.Context, in *MsgCreateAuction, opts ...grpc.CallOption) (*MsgCreateAuctionResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgCreateAuctionResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_CreateAuction_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_CreateAuction_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -61,8 +64,9 @@ func (c *msgClient) CreateAuction(ctx context.Context, in *MsgCreateAuction, opt
|
||||
}
|
||||
|
||||
func (c *msgClient) CommitBid(ctx context.Context, in *MsgCommitBid, opts ...grpc.CallOption) (*MsgCommitBidResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgCommitBidResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_CommitBid_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_CommitBid_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -70,8 +74,9 @@ func (c *msgClient) CommitBid(ctx context.Context, in *MsgCommitBid, opts ...grp
|
||||
}
|
||||
|
||||
func (c *msgClient) RevealBid(ctx context.Context, in *MsgRevealBid, opts ...grpc.CallOption) (*MsgRevealBidResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgRevealBidResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_RevealBid_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_RevealBid_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -79,8 +84,9 @@ func (c *msgClient) RevealBid(ctx context.Context, in *MsgRevealBid, opts ...grp
|
||||
}
|
||||
|
||||
func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgUpdateParamsResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -88,8 +94,9 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts
|
||||
}
|
||||
|
||||
func (c *msgClient) ReleaseFunds(ctx context.Context, in *MsgReleaseFunds, opts ...grpc.CallOption) (*MsgReleaseFundsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgReleaseFundsResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_ReleaseFunds_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_ReleaseFunds_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -98,7 +105,9 @@ func (c *msgClient) ReleaseFunds(ctx context.Context, in *MsgReleaseFunds, opts
|
||||
|
||||
// MsgServer is the server API for Msg service.
|
||||
// All implementations must embed UnimplementedMsgServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Tx defines the gRPC tx interface
|
||||
type MsgServer interface {
|
||||
// CreateAuction is the command for creating an auction
|
||||
CreateAuction(context.Context, *MsgCreateAuction) (*MsgCreateAuctionResponse, error)
|
||||
@ -114,9 +123,12 @@ type MsgServer interface {
|
||||
mustEmbedUnimplementedMsgServer()
|
||||
}
|
||||
|
||||
// UnimplementedMsgServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedMsgServer struct {
|
||||
}
|
||||
// UnimplementedMsgServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedMsgServer struct{}
|
||||
|
||||
func (UnimplementedMsgServer) CreateAuction(context.Context, *MsgCreateAuction) (*MsgCreateAuctionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateAuction not implemented")
|
||||
@ -134,6 +146,7 @@ func (UnimplementedMsgServer) ReleaseFunds(context.Context, *MsgReleaseFunds) (*
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReleaseFunds not implemented")
|
||||
}
|
||||
func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {}
|
||||
func (UnimplementedMsgServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeMsgServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MsgServer will
|
||||
@ -143,6 +156,13 @@ type UnsafeMsgServer interface {
|
||||
}
|
||||
|
||||
func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) {
|
||||
// If the following call pancis, it indicates UnimplementedMsgServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Msg_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/bond/v1/query.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Query_Params_FullMethodName = "/cerc.bond.v1.Query/Params"
|
||||
@ -29,6 +29,8 @@ const (
|
||||
// QueryClient is the client API for Query service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Query defines the gRPC querier service for bond module
|
||||
type QueryClient interface {
|
||||
// Params queries bonds module params.
|
||||
Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
|
||||
@ -51,8 +53,9 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient {
|
||||
}
|
||||
|
||||
func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryParamsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -60,8 +63,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
|
||||
}
|
||||
|
||||
func (c *queryClient) Bonds(ctx context.Context, in *QueryBondsRequest, opts ...grpc.CallOption) (*QueryBondsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryBondsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Bonds_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Bonds_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -69,8 +73,9 @@ func (c *queryClient) Bonds(ctx context.Context, in *QueryBondsRequest, opts ...
|
||||
}
|
||||
|
||||
func (c *queryClient) GetBondById(ctx context.Context, in *QueryGetBondByIdRequest, opts ...grpc.CallOption) (*QueryGetBondByIdResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetBondByIdResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetBondById_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetBondById_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,8 +83,9 @@ func (c *queryClient) GetBondById(ctx context.Context, in *QueryGetBondByIdReque
|
||||
}
|
||||
|
||||
func (c *queryClient) GetBondsByOwner(ctx context.Context, in *QueryGetBondsByOwnerRequest, opts ...grpc.CallOption) (*QueryGetBondsByOwnerResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetBondsByOwnerResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetBondsByOwner_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetBondsByOwner_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -87,8 +93,9 @@ func (c *queryClient) GetBondsByOwner(ctx context.Context, in *QueryGetBondsByOw
|
||||
}
|
||||
|
||||
func (c *queryClient) GetBondModuleBalance(ctx context.Context, in *QueryGetBondModuleBalanceRequest, opts ...grpc.CallOption) (*QueryGetBondModuleBalanceResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetBondModuleBalanceResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetBondModuleBalance_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetBondModuleBalance_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -97,7 +104,9 @@ func (c *queryClient) GetBondModuleBalance(ctx context.Context, in *QueryGetBond
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
// All implementations must embed UnimplementedQueryServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Query defines the gRPC querier service for bond module
|
||||
type QueryServer interface {
|
||||
// Params queries bonds module params.
|
||||
Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
|
||||
@ -112,9 +121,12 @@ type QueryServer interface {
|
||||
mustEmbedUnimplementedQueryServer()
|
||||
}
|
||||
|
||||
// UnimplementedQueryServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedQueryServer struct {
|
||||
}
|
||||
// UnimplementedQueryServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedQueryServer struct{}
|
||||
|
||||
func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
|
||||
@ -132,6 +144,7 @@ func (UnimplementedQueryServer) GetBondModuleBalance(context.Context, *QueryGetB
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBondModuleBalance not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {}
|
||||
func (UnimplementedQueryServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeQueryServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to QueryServer will
|
||||
@ -141,6 +154,13 @@ type UnsafeQueryServer interface {
|
||||
}
|
||||
|
||||
func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) {
|
||||
// If the following call pancis, it indicates UnimplementedQueryServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Query_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/bond/v1/tx.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Msg_CreateBond_FullMethodName = "/cerc.bond.v1.Msg/CreateBond"
|
||||
@ -29,6 +29,8 @@ const (
|
||||
// MsgClient is the client API for Msg service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Msg defines the bond Msg service.
|
||||
type MsgClient interface {
|
||||
// CreateBond defines a method for creating a new bond.
|
||||
CreateBond(ctx context.Context, in *MsgCreateBond, opts ...grpc.CallOption) (*MsgCreateBondResponse, error)
|
||||
@ -52,8 +54,9 @@ func NewMsgClient(cc grpc.ClientConnInterface) MsgClient {
|
||||
}
|
||||
|
||||
func (c *msgClient) CreateBond(ctx context.Context, in *MsgCreateBond, opts ...grpc.CallOption) (*MsgCreateBondResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgCreateBondResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_CreateBond_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_CreateBond_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -61,8 +64,9 @@ func (c *msgClient) CreateBond(ctx context.Context, in *MsgCreateBond, opts ...g
|
||||
}
|
||||
|
||||
func (c *msgClient) RefillBond(ctx context.Context, in *MsgRefillBond, opts ...grpc.CallOption) (*MsgRefillBondResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgRefillBondResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_RefillBond_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_RefillBond_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -70,8 +74,9 @@ func (c *msgClient) RefillBond(ctx context.Context, in *MsgRefillBond, opts ...g
|
||||
}
|
||||
|
||||
func (c *msgClient) WithdrawBond(ctx context.Context, in *MsgWithdrawBond, opts ...grpc.CallOption) (*MsgWithdrawBondResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgWithdrawBondResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_WithdrawBond_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_WithdrawBond_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -79,8 +84,9 @@ func (c *msgClient) WithdrawBond(ctx context.Context, in *MsgWithdrawBond, opts
|
||||
}
|
||||
|
||||
func (c *msgClient) CancelBond(ctx context.Context, in *MsgCancelBond, opts ...grpc.CallOption) (*MsgCancelBondResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgCancelBondResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_CancelBond_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_CancelBond_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -88,8 +94,9 @@ func (c *msgClient) CancelBond(ctx context.Context, in *MsgCancelBond, opts ...g
|
||||
}
|
||||
|
||||
func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgUpdateParamsResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -98,7 +105,9 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts
|
||||
|
||||
// MsgServer is the server API for Msg service.
|
||||
// All implementations must embed UnimplementedMsgServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Msg defines the bond Msg service.
|
||||
type MsgServer interface {
|
||||
// CreateBond defines a method for creating a new bond.
|
||||
CreateBond(context.Context, *MsgCreateBond) (*MsgCreateBondResponse, error)
|
||||
@ -114,9 +123,12 @@ type MsgServer interface {
|
||||
mustEmbedUnimplementedMsgServer()
|
||||
}
|
||||
|
||||
// UnimplementedMsgServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedMsgServer struct {
|
||||
}
|
||||
// UnimplementedMsgServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedMsgServer struct{}
|
||||
|
||||
func (UnimplementedMsgServer) CreateBond(context.Context, *MsgCreateBond) (*MsgCreateBondResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateBond not implemented")
|
||||
@ -134,6 +146,7 @@ func (UnimplementedMsgServer) UpdateParams(context.Context, *MsgUpdateParams) (*
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented")
|
||||
}
|
||||
func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {}
|
||||
func (UnimplementedMsgServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeMsgServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MsgServer will
|
||||
@ -143,6 +156,13 @@ type UnsafeMsgServer interface {
|
||||
}
|
||||
|
||||
func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) {
|
||||
// If the following call pancis, it indicates UnimplementedMsgServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Msg_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@ -426,7 +426,7 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods {
|
||||
var (
|
||||
md_Participant protoreflect.MessageDescriptor
|
||||
fd_Participant_cosmos_address protoreflect.FieldDescriptor
|
||||
fd_Participant_nitro_address protoreflect.FieldDescriptor
|
||||
fd_Participant_public_key protoreflect.FieldDescriptor
|
||||
fd_Participant_role protoreflect.FieldDescriptor
|
||||
fd_Participant_kyc_id protoreflect.FieldDescriptor
|
||||
)
|
||||
@ -435,7 +435,7 @@ func init() {
|
||||
file_cerc_onboarding_v1_onboarding_proto_init()
|
||||
md_Participant = File_cerc_onboarding_v1_onboarding_proto.Messages().ByName("Participant")
|
||||
fd_Participant_cosmos_address = md_Participant.Fields().ByName("cosmos_address")
|
||||
fd_Participant_nitro_address = md_Participant.Fields().ByName("nitro_address")
|
||||
fd_Participant_public_key = md_Participant.Fields().ByName("public_key")
|
||||
fd_Participant_role = md_Participant.Fields().ByName("role")
|
||||
fd_Participant_kyc_id = md_Participant.Fields().ByName("kyc_id")
|
||||
}
|
||||
@ -511,9 +511,9 @@ func (x *fastReflection_Participant) Range(f func(protoreflect.FieldDescriptor,
|
||||
return
|
||||
}
|
||||
}
|
||||
if x.NitroAddress != "" {
|
||||
value := protoreflect.ValueOfString(x.NitroAddress)
|
||||
if !f(fd_Participant_nitro_address, value) {
|
||||
if len(x.PublicKey) != 0 {
|
||||
value := protoreflect.ValueOfBytes(x.PublicKey)
|
||||
if !f(fd_Participant_public_key, value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -546,8 +546,8 @@ func (x *fastReflection_Participant) Has(fd protoreflect.FieldDescriptor) bool {
|
||||
switch fd.FullName() {
|
||||
case "cerc.onboarding.v1.Participant.cosmos_address":
|
||||
return x.CosmosAddress != ""
|
||||
case "cerc.onboarding.v1.Participant.nitro_address":
|
||||
return x.NitroAddress != ""
|
||||
case "cerc.onboarding.v1.Participant.public_key":
|
||||
return len(x.PublicKey) != 0
|
||||
case "cerc.onboarding.v1.Participant.role":
|
||||
return x.Role != ""
|
||||
case "cerc.onboarding.v1.Participant.kyc_id":
|
||||
@ -570,8 +570,8 @@ func (x *fastReflection_Participant) Clear(fd protoreflect.FieldDescriptor) {
|
||||
switch fd.FullName() {
|
||||
case "cerc.onboarding.v1.Participant.cosmos_address":
|
||||
x.CosmosAddress = ""
|
||||
case "cerc.onboarding.v1.Participant.nitro_address":
|
||||
x.NitroAddress = ""
|
||||
case "cerc.onboarding.v1.Participant.public_key":
|
||||
x.PublicKey = nil
|
||||
case "cerc.onboarding.v1.Participant.role":
|
||||
x.Role = ""
|
||||
case "cerc.onboarding.v1.Participant.kyc_id":
|
||||
@ -595,9 +595,9 @@ func (x *fastReflection_Participant) Get(descriptor protoreflect.FieldDescriptor
|
||||
case "cerc.onboarding.v1.Participant.cosmos_address":
|
||||
value := x.CosmosAddress
|
||||
return protoreflect.ValueOfString(value)
|
||||
case "cerc.onboarding.v1.Participant.nitro_address":
|
||||
value := x.NitroAddress
|
||||
return protoreflect.ValueOfString(value)
|
||||
case "cerc.onboarding.v1.Participant.public_key":
|
||||
value := x.PublicKey
|
||||
return protoreflect.ValueOfBytes(value)
|
||||
case "cerc.onboarding.v1.Participant.role":
|
||||
value := x.Role
|
||||
return protoreflect.ValueOfString(value)
|
||||
@ -626,8 +626,8 @@ func (x *fastReflection_Participant) Set(fd protoreflect.FieldDescriptor, value
|
||||
switch fd.FullName() {
|
||||
case "cerc.onboarding.v1.Participant.cosmos_address":
|
||||
x.CosmosAddress = value.Interface().(string)
|
||||
case "cerc.onboarding.v1.Participant.nitro_address":
|
||||
x.NitroAddress = value.Interface().(string)
|
||||
case "cerc.onboarding.v1.Participant.public_key":
|
||||
x.PublicKey = value.Bytes()
|
||||
case "cerc.onboarding.v1.Participant.role":
|
||||
x.Role = value.Interface().(string)
|
||||
case "cerc.onboarding.v1.Participant.kyc_id":
|
||||
@ -654,8 +654,8 @@ func (x *fastReflection_Participant) Mutable(fd protoreflect.FieldDescriptor) pr
|
||||
switch fd.FullName() {
|
||||
case "cerc.onboarding.v1.Participant.cosmos_address":
|
||||
panic(fmt.Errorf("field cosmos_address of message cerc.onboarding.v1.Participant is not mutable"))
|
||||
case "cerc.onboarding.v1.Participant.nitro_address":
|
||||
panic(fmt.Errorf("field nitro_address of message cerc.onboarding.v1.Participant is not mutable"))
|
||||
case "cerc.onboarding.v1.Participant.public_key":
|
||||
panic(fmt.Errorf("field public_key of message cerc.onboarding.v1.Participant is not mutable"))
|
||||
case "cerc.onboarding.v1.Participant.role":
|
||||
panic(fmt.Errorf("field role of message cerc.onboarding.v1.Participant is not mutable"))
|
||||
case "cerc.onboarding.v1.Participant.kyc_id":
|
||||
@ -675,8 +675,8 @@ func (x *fastReflection_Participant) NewField(fd protoreflect.FieldDescriptor) p
|
||||
switch fd.FullName() {
|
||||
case "cerc.onboarding.v1.Participant.cosmos_address":
|
||||
return protoreflect.ValueOfString("")
|
||||
case "cerc.onboarding.v1.Participant.nitro_address":
|
||||
return protoreflect.ValueOfString("")
|
||||
case "cerc.onboarding.v1.Participant.public_key":
|
||||
return protoreflect.ValueOfBytes(nil)
|
||||
case "cerc.onboarding.v1.Participant.role":
|
||||
return protoreflect.ValueOfString("")
|
||||
case "cerc.onboarding.v1.Participant.kyc_id":
|
||||
@ -754,7 +754,7 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
|
||||
if l > 0 {
|
||||
n += 1 + l + runtime.Sov(uint64(l))
|
||||
}
|
||||
l = len(x.NitroAddress)
|
||||
l = len(x.PublicKey)
|
||||
if l > 0 {
|
||||
n += 1 + l + runtime.Sov(uint64(l))
|
||||
}
|
||||
@ -809,10 +809,10 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(x.NitroAddress) > 0 {
|
||||
i -= len(x.NitroAddress)
|
||||
copy(dAtA[i:], x.NitroAddress)
|
||||
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.NitroAddress)))
|
||||
if len(x.PublicKey) > 0 {
|
||||
i -= len(x.PublicKey)
|
||||
copy(dAtA[i:], x.PublicKey)
|
||||
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.PublicKey)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
@ -906,9 +906,9 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field NitroAddress", wireType)
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
|
||||
@ -918,23 +918,25 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
if byteLen < 0 {
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
|
||||
}
|
||||
x.NitroAddress = string(dAtA[iNdEx:postIndex])
|
||||
x.PublicKey = append(x.PublicKey[:0], dAtA[iNdEx:postIndex]...)
|
||||
if x.PublicKey == nil {
|
||||
x.PublicKey = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
@ -1577,8 +1579,8 @@ type Participant struct {
|
||||
|
||||
// participant's cosmos (laconic) address
|
||||
CosmosAddress string `protobuf:"bytes,1,opt,name=cosmos_address,json=cosmosAddress,proto3" json:"cosmos_address,omitempty"`
|
||||
// participant's Nitro address
|
||||
NitroAddress string `protobuf:"bytes,2,opt,name=nitro_address,json=nitroAddress,proto3" json:"nitro_address,omitempty"`
|
||||
// full public key used to derive participant's Nitro address
|
||||
PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||
// participant's role (participant | validator)
|
||||
Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"`
|
||||
// participant's KYC receipt ID
|
||||
@ -1612,11 +1614,11 @@ func (x *Participant) GetCosmosAddress() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Participant) GetNitroAddress() string {
|
||||
func (x *Participant) GetPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.NitroAddress
|
||||
return x.PublicKey
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Participant) GetRole() string {
|
||||
@ -1692,46 +1694,43 @@ var file_cerc_onboarding_v1_onboarding_proto_rawDesc = []byte{
|
||||
0x6c, 0x65, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6f, 0x6e, 0x62, 0x6f, 0x61,
|
||||
0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x52, 0x11,
|
||||
0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x64, 0x22, 0xa2, 0x02, 0x0a, 0x0b, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e,
|
||||
0x64, 0x22, 0xed, 0x01, 0x0a, 0x0b, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e,
|
||||
0x74, 0x12, 0x56, 0x0a, 0x0e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72,
|
||||
0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xf2, 0xde, 0x1f, 0x2b, 0x6a,
|
||||
0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72,
|
||||
0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f,
|
||||
0x73, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x0d, 0x63, 0x6f, 0x73, 0x6d,
|
||||
0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x52, 0x0a, 0x0d, 0x6e, 0x69, 0x74,
|
||||
0x72, 0x6f, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x42, 0x2d, 0xf2, 0xde, 0x1f, 0x29, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6e, 0x69, 0x74, 0x72,
|
||||
0x6f, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a,
|
||||
0x22, 0x6e, 0x69, 0x74, 0x72, 0x6f, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52,
|
||||
0x0c, 0x6e, 0x69, 0x74, 0x72, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2f, 0x0a,
|
||||
0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1b, 0xf2, 0xde, 0x1f,
|
||||
0x17, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x20, 0x79, 0x61, 0x6d,
|
||||
0x6c, 0x3a, 0x22, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x36,
|
||||
0x0a, 0x06, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1f,
|
||||
0xf2, 0xde, 0x1f, 0x1b, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64,
|
||||
0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x22, 0x52,
|
||||
0x05, 0x6b, 0x79, 0x63, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x0a, 0x45, 0x74, 0x68, 0x50, 0x61, 0x79,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a,
|
||||
0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22,
|
||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||
0x73, 0x12, 0x2b, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19,
|
||||
0xf2, 0xde, 0x1f, 0x15, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6d, 0x73, 0x67, 0x22, 0x20, 0x79,
|
||||
0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x73, 0x67, 0x22, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x42, 0xd4,
|
||||
0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x6f, 0x6e, 0x62, 0x6f,
|
||||
0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x42, 0x0f, 0x4f, 0x6e, 0x62, 0x6f, 0x61,
|
||||
0x72, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69,
|
||||
0x74, 0x2e, 0x76, 0x64, 0x62, 0x2e, 0x74, 0x6f, 0x2f, 0x63, 0x65, 0x72, 0x63, 0x2d, 0x69, 0x6f,
|
||||
0x2f, 0x6c, 0x61, 0x63, 0x6f, 0x6e, 0x69, 0x63, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x65,
|
||||
0x72, 0x63, 0x2f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31,
|
||||
0x3b, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x76, 0x31, 0xa2, 0x02, 0x03,
|
||||
0x43, 0x4f, 0x58, 0xaa, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x2e, 0x4f, 0x6e, 0x62, 0x6f, 0x61,
|
||||
0x72, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x5c,
|
||||
0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1e,
|
||||
0x43, 0x65, 0x72, 0x63, 0x5c, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c,
|
||||
0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
|
||||
0x14, 0x43, 0x65, 0x72, 0x63, 0x3a, 0x3a, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70,
|
||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1b, 0xf2, 0xde, 0x1f, 0x17, 0x6a, 0x73, 0x6f, 0x6e,
|
||||
0x3a, 0x22, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x72, 0x6f,
|
||||
0x6c, 0x65, 0x22, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x6b, 0x79, 0x63,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1f, 0xf2, 0xde, 0x1f, 0x1b, 0x6a,
|
||||
0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d,
|
||||
0x6c, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x22, 0x52, 0x05, 0x6b, 0x79, 0x63, 0x49,
|
||||
0x64, 0x22, 0x76, 0x0a, 0x0a, 0x45, 0x74, 0x68, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12,
|
||||
0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x42, 0x21, 0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x61, 0x64, 0x64, 0x72,
|
||||
0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||
0x73, 0x73, 0x22, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2b, 0x0a, 0x03,
|
||||
0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xf2, 0xde, 0x1f, 0x15, 0x6a,
|
||||
0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6d, 0x73, 0x67, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22,
|
||||
0x6d, 0x73, 0x67, 0x22, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x42, 0xd4, 0x01, 0x0a, 0x16, 0x63, 0x6f,
|
||||
0x6d, 0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x2e, 0x76, 0x31, 0x42, 0x0f, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x76, 0x64, 0x62,
|
||||
0x2e, 0x74, 0x6f, 0x2f, 0x63, 0x65, 0x72, 0x63, 0x2d, 0x69, 0x6f, 0x2f, 0x6c, 0x61, 0x63, 0x6f,
|
||||
0x6e, 0x69, 0x63, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x65, 0x72, 0x63, 0x2f, 0x6f, 0x6e,
|
||||
0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x6f, 0x6e, 0x62, 0x6f,
|
||||
0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x4f, 0x58, 0xaa, 0x02,
|
||||
0x12, 0x43, 0x65, 0x72, 0x63, 0x2e, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x5c, 0x4f, 0x6e, 0x62, 0x6f, 0x61,
|
||||
0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1e, 0x43, 0x65, 0x72, 0x63, 0x5c,
|
||||
0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50,
|
||||
0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x43, 0x65, 0x72, 0x63,
|
||||
0x3a, 0x3a, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/onboarding/v1/query.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Query_Participants_FullMethodName = "/cerc.onboarding.v1.Query/Participants"
|
||||
@ -27,6 +27,8 @@ const (
|
||||
// QueryClient is the client API for Query service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Query defines the gRPC querier service for onboarding module
|
||||
type QueryClient interface {
|
||||
// Participants queries Participants list
|
||||
Participants(ctx context.Context, in *QueryParticipantsRequest, opts ...grpc.CallOption) (*QueryParticipantsResponse, error)
|
||||
@ -45,8 +47,9 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient {
|
||||
}
|
||||
|
||||
func (c *queryClient) Participants(ctx context.Context, in *QueryParticipantsRequest, opts ...grpc.CallOption) (*QueryParticipantsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryParticipantsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Participants_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Participants_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -54,8 +57,9 @@ func (c *queryClient) Participants(ctx context.Context, in *QueryParticipantsReq
|
||||
}
|
||||
|
||||
func (c *queryClient) GetParticipantByAddress(ctx context.Context, in *QueryGetParticipantByAddressRequest, opts ...grpc.CallOption) (*QueryGetParticipantByAddressResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetParticipantByAddressResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetParticipantByAddress_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetParticipantByAddress_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -63,8 +67,9 @@ func (c *queryClient) GetParticipantByAddress(ctx context.Context, in *QueryGetP
|
||||
}
|
||||
|
||||
func (c *queryClient) GetParticipantByNitroAddress(ctx context.Context, in *QueryGetParticipantByNitroAddressRequest, opts ...grpc.CallOption) (*QueryGetParticipantByNitroAddressResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetParticipantByNitroAddressResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetParticipantByNitroAddress_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetParticipantByNitroAddress_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -73,7 +78,9 @@ func (c *queryClient) GetParticipantByNitroAddress(ctx context.Context, in *Quer
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
// All implementations must embed UnimplementedQueryServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Query defines the gRPC querier service for onboarding module
|
||||
type QueryServer interface {
|
||||
// Participants queries Participants list
|
||||
Participants(context.Context, *QueryParticipantsRequest) (*QueryParticipantsResponse, error)
|
||||
@ -84,9 +91,12 @@ type QueryServer interface {
|
||||
mustEmbedUnimplementedQueryServer()
|
||||
}
|
||||
|
||||
// UnimplementedQueryServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedQueryServer struct {
|
||||
}
|
||||
// UnimplementedQueryServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedQueryServer struct{}
|
||||
|
||||
func (UnimplementedQueryServer) Participants(context.Context, *QueryParticipantsRequest) (*QueryParticipantsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Participants not implemented")
|
||||
@ -98,6 +108,7 @@ func (UnimplementedQueryServer) GetParticipantByNitroAddress(context.Context, *Q
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetParticipantByNitroAddress not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {}
|
||||
func (UnimplementedQueryServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeQueryServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to QueryServer will
|
||||
@ -107,6 +118,13 @@ type UnsafeQueryServer interface {
|
||||
}
|
||||
|
||||
func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) {
|
||||
// If the following call pancis, it indicates UnimplementedQueryServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Query_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/onboarding/v1/tx.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Msg_OnboardParticipant_FullMethodName = "/cerc.onboarding.v1.Msg/OnboardParticipant"
|
||||
@ -25,6 +25,8 @@ const (
|
||||
// MsgClient is the client API for Msg service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Msg defines the onboarding Msg service.
|
||||
type MsgClient interface {
|
||||
// OnboardParticipant defines a method for enrolling a new validator.
|
||||
OnboardParticipant(ctx context.Context, in *MsgOnboardParticipant, opts ...grpc.CallOption) (*MsgOnboardParticipantResponse, error)
|
||||
@ -39,8 +41,9 @@ func NewMsgClient(cc grpc.ClientConnInterface) MsgClient {
|
||||
}
|
||||
|
||||
func (c *msgClient) OnboardParticipant(ctx context.Context, in *MsgOnboardParticipant, opts ...grpc.CallOption) (*MsgOnboardParticipantResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgOnboardParticipantResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_OnboardParticipant_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_OnboardParticipant_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -49,21 +52,27 @@ func (c *msgClient) OnboardParticipant(ctx context.Context, in *MsgOnboardPartic
|
||||
|
||||
// MsgServer is the server API for Msg service.
|
||||
// All implementations must embed UnimplementedMsgServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Msg defines the onboarding Msg service.
|
||||
type MsgServer interface {
|
||||
// OnboardParticipant defines a method for enrolling a new validator.
|
||||
OnboardParticipant(context.Context, *MsgOnboardParticipant) (*MsgOnboardParticipantResponse, error)
|
||||
mustEmbedUnimplementedMsgServer()
|
||||
}
|
||||
|
||||
// UnimplementedMsgServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedMsgServer struct {
|
||||
}
|
||||
// UnimplementedMsgServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedMsgServer struct{}
|
||||
|
||||
func (UnimplementedMsgServer) OnboardParticipant(context.Context, *MsgOnboardParticipant) (*MsgOnboardParticipantResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OnboardParticipant not implemented")
|
||||
}
|
||||
func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {}
|
||||
func (UnimplementedMsgServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeMsgServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MsgServer will
|
||||
@ -73,6 +82,13 @@ type UnsafeMsgServer interface {
|
||||
}
|
||||
|
||||
func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) {
|
||||
// If the following call pancis, it indicates UnimplementedMsgServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Msg_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/registry/v1/query.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Query_Params_FullMethodName = "/cerc.registry.v1.Query/Params"
|
||||
@ -34,6 +34,8 @@ const (
|
||||
// QueryClient is the client API for Query service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Query defines the gRPC querier service for registry module
|
||||
type QueryClient interface {
|
||||
// Params queries the registry module params.
|
||||
Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
|
||||
@ -66,8 +68,9 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient {
|
||||
}
|
||||
|
||||
func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryParamsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -75,8 +78,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
|
||||
}
|
||||
|
||||
func (c *queryClient) Records(ctx context.Context, in *QueryRecordsRequest, opts ...grpc.CallOption) (*QueryRecordsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryRecordsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Records_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Records_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -84,8 +88,9 @@ func (c *queryClient) Records(ctx context.Context, in *QueryRecordsRequest, opts
|
||||
}
|
||||
|
||||
func (c *queryClient) GetRecord(ctx context.Context, in *QueryGetRecordRequest, opts ...grpc.CallOption) (*QueryGetRecordResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetRecordResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetRecord_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetRecord_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -93,8 +98,9 @@ func (c *queryClient) GetRecord(ctx context.Context, in *QueryGetRecordRequest,
|
||||
}
|
||||
|
||||
func (c *queryClient) GetRecordsByBondId(ctx context.Context, in *QueryGetRecordsByBondIdRequest, opts ...grpc.CallOption) (*QueryGetRecordsByBondIdResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetRecordsByBondIdResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetRecordsByBondId_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetRecordsByBondId_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -102,8 +108,9 @@ func (c *queryClient) GetRecordsByBondId(ctx context.Context, in *QueryGetRecord
|
||||
}
|
||||
|
||||
func (c *queryClient) NameRecords(ctx context.Context, in *QueryNameRecordsRequest, opts ...grpc.CallOption) (*QueryNameRecordsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryNameRecordsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_NameRecords_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_NameRecords_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -111,8 +118,9 @@ func (c *queryClient) NameRecords(ctx context.Context, in *QueryNameRecordsReque
|
||||
}
|
||||
|
||||
func (c *queryClient) Whois(ctx context.Context, in *QueryWhoisRequest, opts ...grpc.CallOption) (*QueryWhoisResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryWhoisResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Whois_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Whois_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -120,8 +128,9 @@ func (c *queryClient) Whois(ctx context.Context, in *QueryWhoisRequest, opts ...
|
||||
}
|
||||
|
||||
func (c *queryClient) LookupLrn(ctx context.Context, in *QueryLookupLrnRequest, opts ...grpc.CallOption) (*QueryLookupLrnResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryLookupLrnResponse)
|
||||
err := c.cc.Invoke(ctx, Query_LookupLrn_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_LookupLrn_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -129,8 +138,9 @@ func (c *queryClient) LookupLrn(ctx context.Context, in *QueryLookupLrnRequest,
|
||||
}
|
||||
|
||||
func (c *queryClient) ResolveLrn(ctx context.Context, in *QueryResolveLrnRequest, opts ...grpc.CallOption) (*QueryResolveLrnResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryResolveLrnResponse)
|
||||
err := c.cc.Invoke(ctx, Query_ResolveLrn_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_ResolveLrn_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -138,8 +148,9 @@ func (c *queryClient) ResolveLrn(ctx context.Context, in *QueryResolveLrnRequest
|
||||
}
|
||||
|
||||
func (c *queryClient) GetRegistryModuleBalance(ctx context.Context, in *QueryGetRegistryModuleBalanceRequest, opts ...grpc.CallOption) (*QueryGetRegistryModuleBalanceResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryGetRegistryModuleBalanceResponse)
|
||||
err := c.cc.Invoke(ctx, Query_GetRegistryModuleBalance_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_GetRegistryModuleBalance_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -147,8 +158,9 @@ func (c *queryClient) GetRegistryModuleBalance(ctx context.Context, in *QueryGet
|
||||
}
|
||||
|
||||
func (c *queryClient) Authorities(ctx context.Context, in *QueryAuthoritiesRequest, opts ...grpc.CallOption) (*QueryAuthoritiesResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryAuthoritiesResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Authorities_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Query_Authorities_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -157,7 +169,9 @@ func (c *queryClient) Authorities(ctx context.Context, in *QueryAuthoritiesReque
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
// All implementations must embed UnimplementedQueryServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Query defines the gRPC querier service for registry module
|
||||
type QueryServer interface {
|
||||
// Params queries the registry module params.
|
||||
Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
|
||||
@ -182,9 +196,12 @@ type QueryServer interface {
|
||||
mustEmbedUnimplementedQueryServer()
|
||||
}
|
||||
|
||||
// UnimplementedQueryServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedQueryServer struct {
|
||||
}
|
||||
// UnimplementedQueryServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedQueryServer struct{}
|
||||
|
||||
func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
|
||||
@ -217,6 +234,7 @@ func (UnimplementedQueryServer) Authorities(context.Context, *QueryAuthoritiesRe
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Authorities not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {}
|
||||
func (UnimplementedQueryServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeQueryServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to QueryServer will
|
||||
@ -226,6 +244,13 @@ type UnsafeQueryServer interface {
|
||||
}
|
||||
|
||||
func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) {
|
||||
// If the following call pancis, it indicates UnimplementedQueryServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Query_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@ -1318,7 +1318,7 @@ var (
|
||||
fd_Record_owners protoreflect.FieldDescriptor
|
||||
fd_Record_attributes protoreflect.FieldDescriptor
|
||||
fd_Record_names protoreflect.FieldDescriptor
|
||||
fd_Record_type protoreflect.FieldDescriptor
|
||||
fd_Record_types protoreflect.FieldDescriptor
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -1332,7 +1332,7 @@ func init() {
|
||||
fd_Record_owners = md_Record.Fields().ByName("owners")
|
||||
fd_Record_attributes = md_Record.Fields().ByName("attributes")
|
||||
fd_Record_names = md_Record.Fields().ByName("names")
|
||||
fd_Record_type = md_Record.Fields().ByName("type")
|
||||
fd_Record_types = md_Record.Fields().ByName("types")
|
||||
}
|
||||
|
||||
var _ protoreflect.Message = (*fastReflection_Record)(nil)
|
||||
@ -1448,9 +1448,9 @@ func (x *fastReflection_Record) Range(f func(protoreflect.FieldDescriptor, proto
|
||||
return
|
||||
}
|
||||
}
|
||||
if x.Type_ != "" {
|
||||
value := protoreflect.ValueOfString(x.Type_)
|
||||
if !f(fd_Record_type, value) {
|
||||
if x.Types != "" {
|
||||
value := protoreflect.ValueOfString(x.Types)
|
||||
if !f(fd_Record_types, value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1485,8 +1485,8 @@ func (x *fastReflection_Record) Has(fd protoreflect.FieldDescriptor) bool {
|
||||
return len(x.Attributes) != 0
|
||||
case "cerc.registry.v1.Record.names":
|
||||
return len(x.Names) != 0
|
||||
case "cerc.registry.v1.Record.type":
|
||||
return x.Type_ != ""
|
||||
case "cerc.registry.v1.Record.types":
|
||||
return x.Types != ""
|
||||
default:
|
||||
if fd.IsExtension() {
|
||||
panic(fmt.Errorf("proto3 declared messages do not support extensions: cerc.registry.v1.Record"))
|
||||
@ -1519,8 +1519,8 @@ func (x *fastReflection_Record) Clear(fd protoreflect.FieldDescriptor) {
|
||||
x.Attributes = nil
|
||||
case "cerc.registry.v1.Record.names":
|
||||
x.Names = nil
|
||||
case "cerc.registry.v1.Record.type":
|
||||
x.Type_ = ""
|
||||
case "cerc.registry.v1.Record.types":
|
||||
x.Types = ""
|
||||
default:
|
||||
if fd.IsExtension() {
|
||||
panic(fmt.Errorf("proto3 declared messages do not support extensions: cerc.registry.v1.Record"))
|
||||
@ -1567,8 +1567,8 @@ func (x *fastReflection_Record) Get(descriptor protoreflect.FieldDescriptor) pro
|
||||
}
|
||||
listValue := &_Record_8_list{list: &x.Names}
|
||||
return protoreflect.ValueOfList(listValue)
|
||||
case "cerc.registry.v1.Record.type":
|
||||
value := x.Type_
|
||||
case "cerc.registry.v1.Record.types":
|
||||
value := x.Types
|
||||
return protoreflect.ValueOfString(value)
|
||||
default:
|
||||
if descriptor.IsExtension() {
|
||||
@ -1610,8 +1610,8 @@ func (x *fastReflection_Record) Set(fd protoreflect.FieldDescriptor, value proto
|
||||
lv := value.List()
|
||||
clv := lv.(*_Record_8_list)
|
||||
x.Names = *clv.list
|
||||
case "cerc.registry.v1.Record.type":
|
||||
x.Type_ = value.Interface().(string)
|
||||
case "cerc.registry.v1.Record.types":
|
||||
x.Types = value.Interface().(string)
|
||||
default:
|
||||
if fd.IsExtension() {
|
||||
panic(fmt.Errorf("proto3 declared messages do not support extensions: cerc.registry.v1.Record"))
|
||||
@ -1656,8 +1656,8 @@ func (x *fastReflection_Record) Mutable(fd protoreflect.FieldDescriptor) protore
|
||||
panic(fmt.Errorf("field deleted of message cerc.registry.v1.Record is not mutable"))
|
||||
case "cerc.registry.v1.Record.attributes":
|
||||
panic(fmt.Errorf("field attributes of message cerc.registry.v1.Record is not mutable"))
|
||||
case "cerc.registry.v1.Record.type":
|
||||
panic(fmt.Errorf("field type of message cerc.registry.v1.Record is not mutable"))
|
||||
case "cerc.registry.v1.Record.types":
|
||||
panic(fmt.Errorf("field types of message cerc.registry.v1.Record is not mutable"))
|
||||
default:
|
||||
if fd.IsExtension() {
|
||||
panic(fmt.Errorf("proto3 declared messages do not support extensions: cerc.registry.v1.Record"))
|
||||
@ -1689,7 +1689,7 @@ func (x *fastReflection_Record) NewField(fd protoreflect.FieldDescriptor) protor
|
||||
case "cerc.registry.v1.Record.names":
|
||||
list := []string{}
|
||||
return protoreflect.ValueOfList(&_Record_8_list{list: &list})
|
||||
case "cerc.registry.v1.Record.type":
|
||||
case "cerc.registry.v1.Record.types":
|
||||
return protoreflect.ValueOfString("")
|
||||
default:
|
||||
if fd.IsExtension() {
|
||||
@ -1795,7 +1795,7 @@ func (x *fastReflection_Record) ProtoMethods() *protoiface.Methods {
|
||||
n += 1 + l + runtime.Sov(uint64(l))
|
||||
}
|
||||
}
|
||||
l = len(x.Type_)
|
||||
l = len(x.Types)
|
||||
if l > 0 {
|
||||
n += 1 + l + runtime.Sov(uint64(l))
|
||||
}
|
||||
@ -1828,10 +1828,10 @@ func (x *fastReflection_Record) ProtoMethods() *protoiface.Methods {
|
||||
i -= len(x.unknownFields)
|
||||
copy(dAtA[i:], x.unknownFields)
|
||||
}
|
||||
if len(x.Type_) > 0 {
|
||||
i -= len(x.Type_)
|
||||
copy(dAtA[i:], x.Type_)
|
||||
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Type_)))
|
||||
if len(x.Types) > 0 {
|
||||
i -= len(x.Types)
|
||||
copy(dAtA[i:], x.Types)
|
||||
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Types)))
|
||||
i--
|
||||
dAtA[i] = 0x4a
|
||||
}
|
||||
@ -2195,7 +2195,7 @@ func (x *fastReflection_Record) ProtoMethods() *protoiface.Methods {
|
||||
iNdEx = postIndex
|
||||
case 9:
|
||||
if wireType != 2 {
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Type_", wireType)
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Types", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
@ -2223,7 +2223,7 @@ func (x *fastReflection_Record) ProtoMethods() *protoiface.Methods {
|
||||
if postIndex > l {
|
||||
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
|
||||
}
|
||||
x.Type_ = string(dAtA[iNdEx:postIndex])
|
||||
x.Types = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
@ -6753,7 +6753,7 @@ type Record struct {
|
||||
Owners []string `protobuf:"bytes,6,rep,name=owners,proto3" json:"owners,omitempty"`
|
||||
Attributes []byte `protobuf:"bytes,7,opt,name=attributes,proto3" json:"attributes,omitempty"`
|
||||
Names []string `protobuf:"bytes,8,rep,name=names,proto3" json:"names,omitempty"`
|
||||
Type_ string `protobuf:"bytes,9,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Types string `protobuf:"bytes,9,opt,name=types,proto3" json:"types,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Record) Reset() {
|
||||
@ -6832,9 +6832,9 @@ func (x *Record) GetNames() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Record) GetType_() string {
|
||||
func (x *Record) GetTypes() string {
|
||||
if x != nil {
|
||||
return x.Type_
|
||||
return x.Types
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@ -7352,7 +7352,7 @@ var file_cerc_registry_v1_registry_proto_rawDesc = []byte{
|
||||
0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x61, 0x75, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x62, 0x69, 0x64, 0x22, 0x52, 0x1a,
|
||||
0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x41, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x42, 0x69, 0x64, 0x22, 0x89, 0x04, 0x0a, 0x06, 0x52,
|
||||
0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x42, 0x69, 0x64, 0x22, 0x8b, 0x04, 0x0a, 0x06, 0x52,
|
||||
0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x27, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x42, 0x17, 0xf2, 0xde, 0x1f, 0x13, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x69, 0x64, 0x22,
|
||||
0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x69, 0x64, 0x22, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a,
|
||||
@ -7382,90 +7382,90 @@ var file_cerc_registry_v1_registry_proto_rawDesc = []byte{
|
||||
0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x42, 0x1d, 0xf2,
|
||||
0xde, 0x1f, 0x19, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x20,
|
||||
0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x52, 0x05, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28,
|
||||
0x09, 0x42, 0x1d, 0xf2, 0xde, 0x1f, 0x19, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x74, 0x79, 0x70,
|
||||
0x65, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x74, 0x79, 0x70, 0x65, 0x73, 0x22,
|
||||
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x5b, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x05,
|
||||
0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x65,
|
||||
0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x05, 0x65, 0x6e,
|
||||
0x74, 0x72, 0x79, 0x22, 0xe6, 0x03, 0x0a, 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x75, 0x74, 0x68,
|
||||
0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x5d, 0x0a, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x70,
|
||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
|
||||
0x33, 0xf2, 0xde, 0x1f, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6f, 0x77, 0x6e, 0x65, 0x72,
|
||||
0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x20, 0x79, 0x61, 0x6d,
|
||||
0x6c, 0x3a, 0x22, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
|
||||
0x6b, 0x65, 0x79, 0x22, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x4b, 0x65, 0x79, 0x12, 0x52, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x64,
|
||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2d, 0xf2, 0xde, 0x1f,
|
||||
0x29, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64,
|
||||
0x72, 0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6f, 0x77, 0x6e, 0x65,
|
||||
0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x0c, 0x6f, 0x77, 0x6e, 0x65,
|
||||
0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67,
|
||||
0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x46, 0x0a, 0x0a, 0x61, 0x75, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xf2, 0xde,
|
||||
0x1f, 0x23, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x61, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x75, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x5f, 0x69, 0x64, 0x22, 0x52, 0x09, 0x61, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64,
|
||||
0x12, 0x3a, 0x0a, 0x07, 0x62, 0x6f, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x09, 0x42, 0x21, 0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x62, 0x6f, 0x6e,
|
||||
0x64, 0x5f, 0x69, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x62, 0x6f, 0x6e, 0x64,
|
||||
0x5f, 0x69, 0x64, 0x22, 0x52, 0x06, 0x62, 0x6f, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x6e, 0x0a, 0x0b,
|
||||
0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x31, 0xc8,
|
||||
0xde, 0x1f, 0x00, 0xf2, 0xde, 0x1f, 0x25, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x65, 0x78, 0x70,
|
||||
0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22,
|
||||
0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x90, 0xdf, 0x1f, 0x01,
|
||||
0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x53, 0x0a, 0x09,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x32, 0x0a,
|
||||
0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63,
|
||||
0x65, 0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x22, 0x84, 0x01, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
|
||||
0x12, 0x39, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x21, 0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x45, 0x6e,
|
||||
0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x07, 0x68,
|
||||
0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63,
|
||||
0x65, 0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
||||
0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x39, 0x0a, 0x0f, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69,
|
||||
0x67, 0x68, 0x74, 0x22, 0x74, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
0x12, 0x2b, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xf2,
|
||||
0xde, 0x1f, 0x15, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x73, 0x69, 0x67, 0x22, 0x20, 0x79, 0x61,
|
||||
0x6d, 0x6c, 0x3a, 0x22, 0x73, 0x69, 0x67, 0x22, 0x52, 0x03, 0x73, 0x69, 0x67, 0x12, 0x3a, 0x0a,
|
||||
0x07, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21,
|
||||
0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65,
|
||||
0x79, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79,
|
||||
0x22, 0x52, 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x33, 0x0a, 0x0b, 0x45, 0x78, 0x70,
|
||||
0x69, 0x72, 0x79, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23,
|
||||
0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x42, 0xc4, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x65, 0x72, 0x63,
|
||||
0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x52, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3b, 0x67,
|
||||
0x69, 0x74, 0x2e, 0x76, 0x64, 0x62, 0x2e, 0x74, 0x6f, 0x2f, 0x63, 0x65, 0x72, 0x63, 0x2d, 0x69,
|
||||
0x6f, 0x2f, 0x6c, 0x61, 0x63, 0x6f, 0x6e, 0x69, 0x63, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63,
|
||||
0x65, 0x72, 0x63, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x76, 0x31, 0x3b,
|
||||
0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x52, 0x58,
|
||||
0xaa, 0x02, 0x10, 0x43, 0x65, 0x72, 0x63, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
|
||||
0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x43, 0x65, 0x72, 0x63, 0x5c, 0x52, 0x65, 0x67, 0x69, 0x73,
|
||||
0x74, 0x72, 0x79, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1c, 0x43, 0x65, 0x72, 0x63, 0x5c, 0x52, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x3a, 0x3a, 0x52, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
0x6d, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01,
|
||||
0x28, 0x09, 0x42, 0x1d, 0xf2, 0xde, 0x1f, 0x19, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x74, 0x79,
|
||||
0x70, 0x65, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x74, 0x79, 0x70, 0x65, 0x73,
|
||||
0x22, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68,
|
||||
0x6f, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35,
|
||||
0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
|
||||
0x63, 0x65, 0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x05,
|
||||
0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xe6, 0x03, 0x0a, 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x75,
|
||||
0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x5d, 0x0a, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72,
|
||||
0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x42, 0x33, 0xf2, 0xde, 0x1f, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6f, 0x77, 0x6e,
|
||||
0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x20, 0x79,
|
||||
0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x52, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f,
|
||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2d, 0xf2,
|
||||
0xde, 0x1f, 0x29, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61,
|
||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6f, 0x77,
|
||||
0x6e, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x0c, 0x6f, 0x77,
|
||||
0x6e, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65,
|
||||
0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67,
|
||||
0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x46, 0x0a, 0x0a, 0x61, 0x75,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27,
|
||||
0xf2, 0xde, 0x1f, 0x23, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x61, 0x75, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x5f, 0x69, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x75, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x52, 0x09, 0x61, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x49, 0x64, 0x12, 0x3a, 0x0a, 0x07, 0x62, 0x6f, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x09, 0x42, 0x21, 0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x62,
|
||||
0x6f, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x62, 0x6f,
|
||||
0x6e, 0x64, 0x5f, 0x69, 0x64, 0x22, 0x52, 0x06, 0x62, 0x6f, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x6e,
|
||||
0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42,
|
||||
0x31, 0xc8, 0xde, 0x1f, 0x00, 0xf2, 0xde, 0x1f, 0x25, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x65,
|
||||
0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c,
|
||||
0x3a, 0x22, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x90, 0xdf,
|
||||
0x1f, 0x01, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x53,
|
||||
0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x32, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
|
||||
0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x05, 0x65, 0x6e,
|
||||
0x74, 0x72, 0x79, 0x22, 0x84, 0x01, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f,
|
||||
0x72, 0x64, 0x12, 0x39, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||
0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a,
|
||||
0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21,
|
||||
0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x52, 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x39, 0x0a, 0x0f, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x0e, 0x0a,
|
||||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x74, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||
0x72, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
|
||||
0x19, 0xf2, 0xde, 0x1f, 0x15, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x73, 0x69, 0x67, 0x22, 0x20,
|
||||
0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x73, 0x69, 0x67, 0x22, 0x52, 0x03, 0x73, 0x69, 0x67, 0x12,
|
||||
0x3a, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x42, 0x21, 0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x70, 0x75, 0x62, 0x5f,
|
||||
0x6b, 0x65, 0x79, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x70, 0x75, 0x62, 0x5f, 0x6b,
|
||||
0x65, 0x79, 0x22, 0x52, 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x33, 0x0a, 0x0b, 0x45,
|
||||
0x78, 0x70, 0x69, 0x72, 0x79, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x22, 0x23, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0xc4, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x65,
|
||||
0x72, 0x63, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x42, 0x0d,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
|
||||
0x3b, 0x67, 0x69, 0x74, 0x2e, 0x76, 0x64, 0x62, 0x2e, 0x74, 0x6f, 0x2f, 0x63, 0x65, 0x72, 0x63,
|
||||
0x2d, 0x69, 0x6f, 0x2f, 0x6c, 0x61, 0x63, 0x6f, 0x6e, 0x69, 0x63, 0x64, 0x2f, 0x61, 0x70, 0x69,
|
||||
0x2f, 0x63, 0x65, 0x72, 0x63, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x76,
|
||||
0x31, 0x3b, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43,
|
||||
0x52, 0x58, 0xaa, 0x02, 0x10, 0x43, 0x65, 0x72, 0x63, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||
0x72, 0x79, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x43, 0x65, 0x72, 0x63, 0x5c, 0x52, 0x65, 0x67,
|
||||
0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1c, 0x43, 0x65, 0x72, 0x63, 0x5c,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d,
|
||||
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x3a, 0x3a,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc (unknown)
|
||||
// source: cerc/registry/v1/tx.proto
|
||||
|
||||
@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Msg_SetRecord_FullMethodName = "/cerc.registry.v1.Msg/SetRecord"
|
||||
@ -35,6 +35,8 @@ const (
|
||||
// MsgClient is the client API for Msg service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Msg is a service which exposes the registry functionality
|
||||
type MsgClient interface {
|
||||
// SetRecord records a new record with given payload and bond id
|
||||
SetRecord(ctx context.Context, in *MsgSetRecord, opts ...grpc.CallOption) (*MsgSetRecordResponse, error)
|
||||
@ -70,8 +72,9 @@ func NewMsgClient(cc grpc.ClientConnInterface) MsgClient {
|
||||
}
|
||||
|
||||
func (c *msgClient) SetRecord(ctx context.Context, in *MsgSetRecord, opts ...grpc.CallOption) (*MsgSetRecordResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgSetRecordResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_SetRecord_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_SetRecord_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -79,8 +82,9 @@ func (c *msgClient) SetRecord(ctx context.Context, in *MsgSetRecord, opts ...grp
|
||||
}
|
||||
|
||||
func (c *msgClient) RenewRecord(ctx context.Context, in *MsgRenewRecord, opts ...grpc.CallOption) (*MsgRenewRecordResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgRenewRecordResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_RenewRecord_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_RenewRecord_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -88,8 +92,9 @@ func (c *msgClient) RenewRecord(ctx context.Context, in *MsgRenewRecord, opts ..
|
||||
}
|
||||
|
||||
func (c *msgClient) AssociateBond(ctx context.Context, in *MsgAssociateBond, opts ...grpc.CallOption) (*MsgAssociateBondResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgAssociateBondResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_AssociateBond_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_AssociateBond_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -97,8 +102,9 @@ func (c *msgClient) AssociateBond(ctx context.Context, in *MsgAssociateBond, opt
|
||||
}
|
||||
|
||||
func (c *msgClient) DissociateBond(ctx context.Context, in *MsgDissociateBond, opts ...grpc.CallOption) (*MsgDissociateBondResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgDissociateBondResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_DissociateBond_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_DissociateBond_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -106,8 +112,9 @@ func (c *msgClient) DissociateBond(ctx context.Context, in *MsgDissociateBond, o
|
||||
}
|
||||
|
||||
func (c *msgClient) DissociateRecords(ctx context.Context, in *MsgDissociateRecords, opts ...grpc.CallOption) (*MsgDissociateRecordsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgDissociateRecordsResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_DissociateRecords_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_DissociateRecords_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -115,8 +122,9 @@ func (c *msgClient) DissociateRecords(ctx context.Context, in *MsgDissociateReco
|
||||
}
|
||||
|
||||
func (c *msgClient) ReassociateRecords(ctx context.Context, in *MsgReassociateRecords, opts ...grpc.CallOption) (*MsgReassociateRecordsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgReassociateRecordsResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_ReassociateRecords_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_ReassociateRecords_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -124,8 +132,9 @@ func (c *msgClient) ReassociateRecords(ctx context.Context, in *MsgReassociateRe
|
||||
}
|
||||
|
||||
func (c *msgClient) SetName(ctx context.Context, in *MsgSetName, opts ...grpc.CallOption) (*MsgSetNameResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgSetNameResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_SetName_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_SetName_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -133,8 +142,9 @@ func (c *msgClient) SetName(ctx context.Context, in *MsgSetName, opts ...grpc.Ca
|
||||
}
|
||||
|
||||
func (c *msgClient) DeleteName(ctx context.Context, in *MsgDeleteName, opts ...grpc.CallOption) (*MsgDeleteNameResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgDeleteNameResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_DeleteName_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_DeleteName_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -142,8 +152,9 @@ func (c *msgClient) DeleteName(ctx context.Context, in *MsgDeleteName, opts ...g
|
||||
}
|
||||
|
||||
func (c *msgClient) ReserveAuthority(ctx context.Context, in *MsgReserveAuthority, opts ...grpc.CallOption) (*MsgReserveAuthorityResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgReserveAuthorityResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_ReserveAuthority_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_ReserveAuthority_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -151,8 +162,9 @@ func (c *msgClient) ReserveAuthority(ctx context.Context, in *MsgReserveAuthorit
|
||||
}
|
||||
|
||||
func (c *msgClient) SetAuthorityBond(ctx context.Context, in *MsgSetAuthorityBond, opts ...grpc.CallOption) (*MsgSetAuthorityBondResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgSetAuthorityBondResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_SetAuthorityBond_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_SetAuthorityBond_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -160,8 +172,9 @@ func (c *msgClient) SetAuthorityBond(ctx context.Context, in *MsgSetAuthorityBon
|
||||
}
|
||||
|
||||
func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MsgUpdateParamsResponse)
|
||||
err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, Msg_UpdateParams_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -170,7 +183,9 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts
|
||||
|
||||
// MsgServer is the server API for Msg service.
|
||||
// All implementations must embed UnimplementedMsgServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Msg is a service which exposes the registry functionality
|
||||
type MsgServer interface {
|
||||
// SetRecord records a new record with given payload and bond id
|
||||
SetRecord(context.Context, *MsgSetRecord) (*MsgSetRecordResponse, error)
|
||||
@ -198,9 +213,12 @@ type MsgServer interface {
|
||||
mustEmbedUnimplementedMsgServer()
|
||||
}
|
||||
|
||||
// UnimplementedMsgServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedMsgServer struct {
|
||||
}
|
||||
// UnimplementedMsgServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedMsgServer struct{}
|
||||
|
||||
func (UnimplementedMsgServer) SetRecord(context.Context, *MsgSetRecord) (*MsgSetRecordResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetRecord not implemented")
|
||||
@ -236,6 +254,7 @@ func (UnimplementedMsgServer) UpdateParams(context.Context, *MsgUpdateParams) (*
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented")
|
||||
}
|
||||
func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {}
|
||||
func (UnimplementedMsgServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeMsgServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MsgServer will
|
||||
@ -245,6 +264,13 @@ type UnsafeMsgServer interface {
|
||||
}
|
||||
|
||||
func RegisterMsgServer(s grpc.ServiceRegistrar, srv MsgServer) {
|
||||
// If the following call pancis, it indicates UnimplementedMsgServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Msg_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
276
app/app.go
276
app/app.go
@ -2,91 +2,90 @@ package app
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"fmt"
|
||||
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
|
||||
"cosmossdk.io/core/appconfig"
|
||||
coreserver "cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
"cosmossdk.io/runtime/v2"
|
||||
serverstore "cosmossdk.io/server/v2/store"
|
||||
"cosmossdk.io/store/v2"
|
||||
"cosmossdk.io/store/v2/commitment/iavlv2"
|
||||
"cosmossdk.io/store/v2/root"
|
||||
basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject"
|
||||
bankkeeper "cosmossdk.io/x/bank/keeper"
|
||||
consensuskeeper "cosmossdk.io/x/consensus/keeper"
|
||||
distrkeeper "cosmossdk.io/x/distribution/keeper"
|
||||
govkeeper "cosmossdk.io/x/gov/keeper"
|
||||
slashingkeeper "cosmossdk.io/x/slashing/keeper"
|
||||
stakingkeeper "cosmossdk.io/x/staking/keeper"
|
||||
|
||||
auctionkeeper "git.vdb.to/cerc-io/laconicd/x/auction/keeper"
|
||||
bondkeeper "git.vdb.to/cerc-io/laconicd/x/bond/keeper"
|
||||
onboardingkeeper "git.vdb.to/cerc-io/laconicd/x/onboarding/keeper"
|
||||
registrykeeper "git.vdb.to/cerc-io/laconicd/x/registry/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/server/api"
|
||||
"github.com/cosmos/cosmos-sdk/server/config"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
|
||||
crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper"
|
||||
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
|
||||
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
|
||||
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
|
||||
_ "cosmossdk.io/api/cosmos/tx/config/v1" // import for side-effects
|
||||
_ "cosmossdk.io/runtime/v2/services" // import for side-effects
|
||||
_ "cosmossdk.io/x/accounts" // import for side-effects
|
||||
_ "cosmossdk.io/x/bank" // import for side-effects
|
||||
_ "cosmossdk.io/x/consensus" // import for side-effects
|
||||
_ "cosmossdk.io/x/distribution" // import for side-effects
|
||||
_ "cosmossdk.io/x/gov" // import for side-effects
|
||||
_ "cosmossdk.io/x/mint" // import for side-effects
|
||||
_ "cosmossdk.io/x/protocolpool" // import for side-effects
|
||||
_ "cosmossdk.io/x/slashing" // import for side-effects
|
||||
_ "cosmossdk.io/x/staking" // import for side-effects
|
||||
_ "git.vdb.to/cerc-io/laconicd/x/auction/module" // import for side-effects
|
||||
_ "git.vdb.to/cerc-io/laconicd/x/bond/module" // import for side-effects
|
||||
_ "git.vdb.to/cerc-io/laconicd/x/onboarding/module" // import for side-effects
|
||||
_ "git.vdb.to/cerc-io/laconicd/x/registry/module" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/crypto/codec" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/bank" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/consensus" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/crisis" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/distribution" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/mint" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/slashing" // import for side-effects
|
||||
_ "github.com/cosmos/cosmos-sdk/x/staking" // import for side-effects
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/server/distsig"
|
||||
"git.vdb.to/cerc-io/laconicd/utils"
|
||||
auctionkeeper "git.vdb.to/cerc-io/laconicd/x/auction/keeper"
|
||||
bondkeeper "git.vdb.to/cerc-io/laconicd/x/bond/keeper"
|
||||
nitrokeeper "git.vdb.to/cerc-io/laconicd/x/nitrobank/keeper"
|
||||
onboardingkeeper "git.vdb.to/cerc-io/laconicd/x/onboarding/keeper"
|
||||
registrykeeper "git.vdb.to/cerc-io/laconicd/x/registry/keeper"
|
||||
)
|
||||
|
||||
// DefaultNodeHome default home directories for the application daemon
|
||||
var DefaultNodeHome string
|
||||
|
||||
//go:embed app.yaml
|
||||
var AppConfigYAML []byte
|
||||
|
||||
var (
|
||||
_ runtime.AppI = (*LaconicApp)(nil)
|
||||
_ servertypes.Application = (*LaconicApp)(nil)
|
||||
//go:embed app.yaml
|
||||
AppConfigYAML []byte
|
||||
|
||||
_ = basedepinject.ProvideAccount // TODO: build consensus controlled module accounts
|
||||
)
|
||||
|
||||
type (
|
||||
Tx = transaction.Tx
|
||||
AppBuilder = runtime.AppBuilder[Tx]
|
||||
)
|
||||
|
||||
// LaconicApp extends an ABCI application, but with most of its parameters exported.
|
||||
// They are exported for convenience in creating helper functions, as object
|
||||
// capabilities aren't needed for testing.
|
||||
type LaconicApp struct {
|
||||
*runtime.App
|
||||
legacyAmino *codec.LegacyAmino
|
||||
type LaconicApp[T Tx] struct {
|
||||
*runtime.App[T]
|
||||
// legacyAmino *codec.LegacyAmino
|
||||
appCodec codec.Codec
|
||||
txConfig client.TxConfig
|
||||
interfaceRegistry codectypes.InterfaceRegistry
|
||||
store store.RootStore
|
||||
distsigManager *distsig.Manager
|
||||
|
||||
// keepers
|
||||
// basic keepers
|
||||
AccountKeeper authkeeper.AccountKeeper
|
||||
BankKeeper bankkeeper.Keeper
|
||||
StakingKeeper *stakingkeeper.Keeper
|
||||
SlashingKeeper slashingkeeper.Keeper
|
||||
DistrKeeper distrkeeper.Keeper
|
||||
GovKeeper *govkeeper.Keeper
|
||||
CrisisKeeper *crisiskeeper.Keeper
|
||||
ConsensusParamsKeeper consensuskeeper.Keeper
|
||||
|
||||
// laconic keepers
|
||||
@ -94,141 +93,128 @@ type LaconicApp struct {
|
||||
BondKeeper *bondkeeper.Keeper
|
||||
RegistryKeeper registrykeeper.Keeper
|
||||
OnboardingKeeper *onboardingkeeper.Keeper
|
||||
|
||||
// simulation manager
|
||||
sm *module.SimulationManager
|
||||
}
|
||||
|
||||
func init() {
|
||||
userHomeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
DefaultNodeHome = filepath.Join(userHomeDir, ".laconicd")
|
||||
NitroKeeper *nitrokeeper.Keeper
|
||||
}
|
||||
|
||||
// AppConfig returns the default app config.
|
||||
func AppConfig() depinject.Config {
|
||||
return depinject.Configs(
|
||||
appconfig.LoadYAML(AppConfigYAML),
|
||||
runtime.DefaultServiceBindings(),
|
||||
depinject.Supply(
|
||||
// supply custom module basics
|
||||
map[string]module.AppModuleBasic{
|
||||
genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
|
||||
govtypes.ModuleName: gov.NewAppModuleBasic(
|
||||
[]govclient.ProposalHandler{
|
||||
paramsclient.ProposalHandler,
|
||||
},
|
||||
),
|
||||
},
|
||||
utils.NewAddressCodec,
|
||||
utils.NewValAddressCodec,
|
||||
utils.NewConsAddressCodec,
|
||||
),
|
||||
depinject.Provide(
|
||||
codec.ProvideInterfaceRegistry,
|
||||
codec.ProvideAddressCodec,
|
||||
codec.ProvideProtoCodec,
|
||||
codec.ProvideLegacyAmino, // note: needed by ProvideAppBuilder (runtime/v2)
|
||||
ProvideRootStoreConfig,
|
||||
distsig.ProvideManager,
|
||||
|
||||
// // inject desired account types:
|
||||
// basedepinject.ProvideAccount,
|
||||
// multisigdepinject.ProvideAccount,
|
||||
// lockupdepinject.ProvideAllLockupAccounts,
|
||||
|
||||
// // provide base account options
|
||||
// basedepinject.ProvideSecp256K1PubKey,
|
||||
),
|
||||
depinject.Invoke(
|
||||
std.RegisterInterfaces,
|
||||
// std.RegisterLegacyAminoCodec,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// NewLaconicApp returns a reference to an initialized LaconicApp.
|
||||
func NewLaconicApp(
|
||||
logger log.Logger,
|
||||
db dbm.DB,
|
||||
traceStore io.Writer,
|
||||
loadLatest bool,
|
||||
appOpts servertypes.AppOptions,
|
||||
baseAppOptions ...func(*baseapp.BaseApp),
|
||||
) (*LaconicApp, error) {
|
||||
func NewLaconicApp[T Tx](
|
||||
config depinject.Config,
|
||||
outputs ...any,
|
||||
) (*LaconicApp[T], error) {
|
||||
var (
|
||||
app = &LaconicApp{}
|
||||
appBuilder *runtime.AppBuilder
|
||||
app LaconicApp[T]
|
||||
appBuilder *runtime.AppBuilder[T]
|
||||
storeBuilder root.Builder
|
||||
err error
|
||||
)
|
||||
|
||||
if err := depinject.Inject(
|
||||
depinject.Configs(
|
||||
AppConfig(),
|
||||
depinject.Supply(
|
||||
logger,
|
||||
appOpts,
|
||||
),
|
||||
),
|
||||
outputs = append(outputs,
|
||||
&storeBuilder,
|
||||
&appBuilder,
|
||||
&app.appCodec,
|
||||
&app.legacyAmino,
|
||||
// &app.legacyAmino,
|
||||
&app.txConfig,
|
||||
&app.interfaceRegistry,
|
||||
&app.distsigManager,
|
||||
// modules
|
||||
&app.StakingKeeper,
|
||||
&app.AccountKeeper,
|
||||
&app.BankKeeper,
|
||||
&app.StakingKeeper,
|
||||
&app.SlashingKeeper,
|
||||
&app.DistrKeeper,
|
||||
&app.GovKeeper,
|
||||
&app.CrisisKeeper,
|
||||
&app.ConsensusParamsKeeper,
|
||||
&app.AuctionKeeper,
|
||||
&app.BondKeeper,
|
||||
&app.RegistryKeeper,
|
||||
&app.OnboardingKeeper,
|
||||
)
|
||||
|
||||
if err = depinject.Inject(
|
||||
depinject.Configs(AppConfig(), config),
|
||||
outputs...,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
app.App = appBuilder.Build(db, traceStore, baseAppOptions...)
|
||||
|
||||
// register streaming services
|
||||
if err := app.RegisterStreamingServices(appOpts, app.kvStoreKeys()); err != nil {
|
||||
app.App, err = appBuilder.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/**** Module Options ****/
|
||||
|
||||
app.ModuleManager.RegisterInvariants(app.CrisisKeeper)
|
||||
|
||||
// create the simulation manager and define the order of the modules for deterministic simulations
|
||||
// NOTE: this is not required apps that don't use the simulator for fuzz testing transactions
|
||||
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, make(map[string]module.AppModuleSimulation, 0))
|
||||
app.sm.RegisterStoreDecoders()
|
||||
|
||||
if err := app.Load(loadLatest); err != nil {
|
||||
return nil, err
|
||||
app.store = storeBuilder.Get()
|
||||
if app.store == nil {
|
||||
return nil, fmt.Errorf("store builder did not return a db")
|
||||
}
|
||||
|
||||
return app, nil
|
||||
// TODO: db config correct?
|
||||
// TODO: store metrics, tracer?
|
||||
// TODO: streaming services?
|
||||
// TODO: upgrade handlers?
|
||||
|
||||
if err = app.LoadLatest(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &app, nil
|
||||
}
|
||||
|
||||
// LegacyAmino returns LaconicApp's amino codec.
|
||||
func (app *LaconicApp) LegacyAmino() *codec.LegacyAmino {
|
||||
return app.legacyAmino
|
||||
func (app *LaconicApp[T]) InterfaceRegistry() coreserver.InterfaceRegistry {
|
||||
return app.interfaceRegistry
|
||||
}
|
||||
|
||||
// GetKey returns the KVStoreKey for the provided store key.
|
||||
func (app *LaconicApp) GetKey(storeKey string) *storetypes.KVStoreKey {
|
||||
sk := app.UnsafeFindStoreKey(storeKey)
|
||||
kvStoreKey, ok := sk.(*storetypes.KVStoreKey)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return kvStoreKey
|
||||
}
|
||||
|
||||
func (app *LaconicApp) kvStoreKeys() map[string]*storetypes.KVStoreKey {
|
||||
keys := make(map[string]*storetypes.KVStoreKey)
|
||||
for _, k := range app.GetStoreKeys() {
|
||||
if kv, ok := k.(*storetypes.KVStoreKey); ok {
|
||||
keys[kv.Name()] = kv
|
||||
}
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
// SimulationManager implements the SimulationApp interface
|
||||
func (app *LaconicApp) SimulationManager() *module.SimulationManager {
|
||||
return app.sm
|
||||
}
|
||||
|
||||
// RegisterAPIRoutes registers all application module routes with the provided
|
||||
// API server.
|
||||
func (app *LaconicApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
||||
app.App.RegisterAPIRoutes(apiSvr, apiConfig)
|
||||
// register swagger API in app.go so that other applications can override easily
|
||||
if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
|
||||
panic(err)
|
||||
func (app *LaconicApp[T]) Store() store.RootStore {
|
||||
return app.store
|
||||
}
|
||||
|
||||
func (app *LaconicApp[T]) AppCodec() codec.Codec {
|
||||
return app.appCodec
|
||||
}
|
||||
|
||||
func (app *LaconicApp[T]) DistSigManager() *distsig.Manager {
|
||||
return app.distsigManager
|
||||
}
|
||||
|
||||
func ProvideRootStoreConfig(config runtime.GlobalConfig) (*root.Config, error) {
|
||||
cfg, err := serverstore.UnmarshalConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.Options.IavlV2Config = iavlv2.DefaultConfig()
|
||||
cfg.Options.IavlV2Config.MinimumKeepVersions = int64(cfg.Options.SCPruningOption.KeepRecent)
|
||||
iavlv2.SetGlobalPruneLimit(1)
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
42
app/app.yaml
42
app/app.yaml
@ -1,19 +1,43 @@
|
||||
modules:
|
||||
- name: runtime
|
||||
config:
|
||||
"@type": cosmos.app.runtime.v1alpha1.Module
|
||||
"@type": cosmos.app.runtime.v2.Module
|
||||
app_name: LaconicApp
|
||||
# During begin block slashing happens after distr.BeginBlocker so that
|
||||
# there is nothing left over in the validator fee pool, so as to keep the CanWithdrawInvariant invariant.
|
||||
# NOTE: staking module is required if HistoricalEntries param > 0
|
||||
begin_blockers: [distribution, slashing, staking]
|
||||
end_blockers: [crisis, gov, staking, auction, registry]
|
||||
begin_blockers: [distribution, protocolpool, slashing, staking]
|
||||
end_blockers: [gov, staking, protocolpool, auction, registry]
|
||||
# NOTE: The genutils module must occur after staking so that pools are properly initialized with tokens from genesis accounts.
|
||||
# NOTE: The genutils module must also occur after auth so that it can access the params from auth.
|
||||
init_genesis: [auth, bank, distribution, staking, slashing, gov, crisis, genutil, auction, bond, registry, onboarding]
|
||||
init_genesis:
|
||||
- consensus
|
||||
- accounts
|
||||
- auth
|
||||
- bank
|
||||
- distribution
|
||||
- staking
|
||||
- slashing
|
||||
- gov
|
||||
- genutil
|
||||
- protocolpool
|
||||
- auction
|
||||
- bond
|
||||
- registry
|
||||
- onboarding
|
||||
gas_config:
|
||||
validate_tx_gas_limit: 100000,
|
||||
query_gas_limit: 100000,
|
||||
simulation_gas_limit: 100000,
|
||||
override_store_keys:
|
||||
- module_name: auth
|
||||
kv_store_key: acc
|
||||
skip_store_keys:
|
||||
- tx
|
||||
- validate
|
||||
- genutil
|
||||
- runtime
|
||||
- vesting
|
||||
- name: auth
|
||||
config:
|
||||
"@type": cosmos.auth.module.v1.Module
|
||||
@ -27,6 +51,9 @@ modules:
|
||||
permissions: [burner, staking]
|
||||
- account: gov
|
||||
permissions: [burner]
|
||||
- account: protocolpool
|
||||
- account: stream_acc
|
||||
- account: protocolpool_distr
|
||||
- account: auction
|
||||
- account: auction_burn
|
||||
- account: bond
|
||||
@ -59,9 +86,12 @@ modules:
|
||||
- name: gov
|
||||
config:
|
||||
"@type": cosmos.gov.module.v1.Module
|
||||
- name: crisis
|
||||
- name: accounts
|
||||
config:
|
||||
"@type": cosmos.crisis.module.v1.Module
|
||||
"@type": cosmos.accounts.module.v1.Module
|
||||
- name: protocolpool
|
||||
config:
|
||||
"@type": cosmos.protocolpool.module.v1.Module
|
||||
- name: bond
|
||||
config:
|
||||
"@type": cerc.bond.module.v1.Module
|
||||
|
||||
107
app/app_abci.go
Normal file
107
app/app_abci.go
Normal file
@ -0,0 +1,107 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/gob"
|
||||
|
||||
"cosmossdk.io/core/store"
|
||||
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/server/distsig"
|
||||
"git.vdb.to/cerc-io/laconicd/x/onboarding"
|
||||
)
|
||||
|
||||
func (app *LaconicApp[T]) ExtendVote(
|
||||
ctx context.Context, _ store.ReaderMap, req *abci.ExtendVoteRequest,
|
||||
) (*abci.ExtendVoteResponse, error) {
|
||||
dsm := app.DistSigManager()
|
||||
ourEthAddress := dsm.LongtermEthAddress()
|
||||
us, err := app.OnboardingKeeper.GetParticipantByNitroAddress(ctx, ourEthAddress.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if us == nil { // if we are not a participant, we don't need to do anything
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// // If any OnboardParticipant tx (or any tx that changes validator set) has been processed,
|
||||
// // begin DKG for the new participants. The extension will contain our DKG deals.
|
||||
// newParticipants := false
|
||||
// for _, tx := range req.Txs {
|
||||
// var opMsg onboarding.MsgOnboardParticipant
|
||||
// if err := opMsg.Unmarshal(tx); err != nil {
|
||||
// // we've already processed the tx, so we don't need to look at the message; we know the
|
||||
// // participant set has changed and we need to run DKG.
|
||||
// newParticipants = true
|
||||
// }
|
||||
// }
|
||||
// // TODO: check if responses are processed, generate commits
|
||||
// if !newParticipants {
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
// Get public keys of participants
|
||||
var pubkeys []distsig.Point
|
||||
if err := app.OnboardingKeeper.Participants.Walk(ctx, nil, func(_ string, p onboarding.Participant) (bool, error) {
|
||||
var pubkey distsig.Point
|
||||
if err := pubkey.UnmarshalBinary(p.PublicKey); err != nil {
|
||||
return false, err
|
||||
}
|
||||
pubkeys = append(pubkeys, pubkey)
|
||||
return false, nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !dsm.NeedDKG(pubkeys) {
|
||||
app.Logger().Debug("No change in DSS participants")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err = dsm.StartDKG(req.Height, pubkeys); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
enc := gob.NewEncoder(buf)
|
||||
if err := enc.Encode(dsm.FlushDKGMessages()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var extension []byte
|
||||
if len(buf.Bytes()) != 0 {
|
||||
extension = buf.Bytes()
|
||||
}
|
||||
return &abci.ExtendVoteResponse{
|
||||
VoteExtension: extension,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (app *LaconicApp[T]) VerifyVoteExtension(
|
||||
ctx context.Context, _ store.ReaderMap, req *abci.VerifyVoteExtensionRequest,
|
||||
) (*abci.VerifyVoteExtensionResponse, error) {
|
||||
dec := gob.NewDecoder(bytes.NewReader(req.VoteExtension))
|
||||
var messages distsig.DkgMessages
|
||||
if err := dec.Decode(&messages); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// // This method must be deterministic, so just check that there is a deal for each participant
|
||||
// numParticipants := 0
|
||||
// app.OnboardingKeeper.Participants.Walk(ctx, nil, func(string, onboarding.Participant) (bool, error) {
|
||||
// numParticipants++
|
||||
// return false, nil
|
||||
// })
|
||||
// if len(deals) != numParticipants {
|
||||
// return &abci.VerifyVoteExtensionResponse{
|
||||
// Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT,
|
||||
// }, nil
|
||||
// }
|
||||
|
||||
err := app.DistSigManager().ProcessDKGMessages(&messages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// This method must be deterministic, so just accept whatever for now (TODO: actually verify)
|
||||
return &abci.VerifyVoteExtensionResponse{
|
||||
Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT,
|
||||
}, nil
|
||||
}
|
||||
176
app/app_test.go
Normal file
176
app/app_test.go
Normal file
@ -0,0 +1,176 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/server/distsig"
|
||||
"git.vdb.to/cerc-io/laconicd/utils"
|
||||
"github.com/cometbft/cometbft/types"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/core/comet"
|
||||
context2 "cosmossdk.io/core/context"
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
serverv2store "cosmossdk.io/server/v2/store"
|
||||
"cosmossdk.io/store/v2/db"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/testutil"
|
||||
)
|
||||
|
||||
func NewTestApp(t *testing.T) (*LaconicApp[Tx], context.Context) {
|
||||
t.Helper()
|
||||
|
||||
logger := log.NewTestLogger(t)
|
||||
|
||||
vp := viper.New()
|
||||
vp.Set(serverv2store.FlagAppDBBackend, string(db.DBTypeGoLevelDB))
|
||||
vp.Set(serverv2.FlagHome, t.TempDir())
|
||||
|
||||
// set up long-term distsig key
|
||||
kr := testutil.NewKeyring()
|
||||
accounts := sdktestutil.CreateKeyringAccounts(t, kr, 1)
|
||||
vp.Set(distsig.FlagLongtermKey, accounts[0].Name)
|
||||
|
||||
app, err := NewLaconicApp[Tx](depinject.Configs(
|
||||
depinject.Supply(logger, runtime.GlobalConfig(vp.AllSettings()), kr),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
genesis := app.ModuleManager().DefaultGenesis()
|
||||
|
||||
privVal := mock.NewPV()
|
||||
pubKey, err := privVal.GetPubKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
// create validator set with single validator
|
||||
validator := types.NewValidator(pubKey, 1)
|
||||
valSet := types.NewValidatorSet([]*types.Validator{validator})
|
||||
|
||||
// generate genesis account
|
||||
senderPrivKey := secp256k1.GenPrivKey()
|
||||
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
||||
accAddr, err := app.txConfig.SigningContext().AddressCodec().BytesToString(acc.GetAddress())
|
||||
require.NoError(t, err)
|
||||
balance := banktypes.Balance{
|
||||
Address: accAddr,
|
||||
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000))),
|
||||
}
|
||||
|
||||
genesis, err = simtestutil.GenesisStateWithValSet(
|
||||
app.AppCodec(),
|
||||
utils.NewAddressCodec(),
|
||||
utils.NewValAddressCodec(),
|
||||
genesis,
|
||||
valSet,
|
||||
[]authtypes.GenesisAccount{acc},
|
||||
balance,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
genesisBytes, err := json.Marshal(genesis)
|
||||
require.NoError(t, err)
|
||||
|
||||
st := app.Store()
|
||||
ci, err := st.LastCommitID()
|
||||
require.NoError(t, err)
|
||||
|
||||
bz := sha256.Sum256([]byte{})
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
_, newState, err := app.InitGenesis(
|
||||
ctx,
|
||||
&server.BlockRequest[Tx]{
|
||||
Time: time.Now(),
|
||||
Hash: bz[:],
|
||||
ChainId: "theChain",
|
||||
AppHash: ci.Hash,
|
||||
IsGenesis: true,
|
||||
Height: 1,
|
||||
},
|
||||
genesisBytes,
|
||||
nil,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
changes, err := newState.GetStateChanges()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = st.Commit(&store.Changeset{Version: 1, Changes: changes})
|
||||
require.NoError(t, err)
|
||||
|
||||
return app, ctx
|
||||
}
|
||||
|
||||
func MoveNextBlock(t *testing.T, app *LaconicApp[Tx], ctx context.Context) {
|
||||
t.Helper()
|
||||
|
||||
bz := sha256.Sum256([]byte{})
|
||||
|
||||
st := app.Store()
|
||||
ci, err := st.LastCommitID()
|
||||
require.NoError(t, err)
|
||||
|
||||
height, err := app.LoadLatestHeight()
|
||||
height++
|
||||
require.NoError(t, err)
|
||||
|
||||
// TODO: this is a hack to set the comet info in the context for distribution module dependency.
|
||||
ctx = context.WithValue(ctx, context2.CometInfoKey, comet.Info{
|
||||
Evidence: nil,
|
||||
ValidatorsHash: nil,
|
||||
ProposerAddress: nil,
|
||||
LastCommit: comet.CommitInfo{},
|
||||
})
|
||||
|
||||
_, newState, err := app.DeliverBlock(
|
||||
ctx,
|
||||
&server.BlockRequest[Tx]{
|
||||
Height: height,
|
||||
Time: time.Now(),
|
||||
Hash: bz[:],
|
||||
AppHash: ci.Hash,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
changes, err := newState.GetStateChanges()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = st.Commit(&store.Changeset{Version: height, Changes: changes})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestSimAppExportAndBlockedAddrs_WithOneBlockProduced(t *testing.T) {
|
||||
app, ctx := NewTestApp(t)
|
||||
|
||||
MoveNextBlock(t, app, ctx)
|
||||
|
||||
_, err := app.ExportAppStateAndValidators(false, nil)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestSimAppExportAndBlockedAddrs_NoBlocksProduced(t *testing.T) {
|
||||
app, _ := NewTestApp(t)
|
||||
|
||||
_, err := app.ExportAppStateAndValidators(false, nil)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
271
app/export.go
271
app/export.go
@ -1,243 +1,54 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"context"
|
||||
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"cosmossdk.io/runtime/v2/services"
|
||||
"cosmossdk.io/x/staking"
|
||||
|
||||
v2 "github.com/cosmos/cosmos-sdk/x/genutil/v2"
|
||||
)
|
||||
|
||||
// ExportAppStateAndValidators exports the state of the application for a genesis file.
|
||||
func (app *LaconicApp) ExportAppStateAndValidators(
|
||||
// ExportAppStateAndValidators exports the state of the application for a genesis
|
||||
// file.
|
||||
// This is a demonstration of how to export a genesis file. Export may need extended at
|
||||
// the user discretion for cleaning the genesis state at the end provided with jailAllowedAddrs
|
||||
// Same applies for forZeroHeight preprocessing.
|
||||
func (app *LaconicApp[T]) ExportAppStateAndValidators(
|
||||
forZeroHeight bool,
|
||||
jailAllowedAddrs []string,
|
||||
modulesToExport []string,
|
||||
) (servertypes.ExportedApp, error) {
|
||||
// as if they could withdraw from the start of the next block
|
||||
ctx := app.NewContextLegacy(true, tmproto.Header{Height: app.LastBlockHeight()})
|
||||
) (v2.ExportedApp, error) {
|
||||
ctx := context.Background()
|
||||
var exportedApp v2.ExportedApp
|
||||
|
||||
// We export at last height + 1, because that's the height at which
|
||||
// CometBFT will start InitChain.
|
||||
height := app.LastBlockHeight() + 1
|
||||
latestHeight, err := app.LoadLatestHeight()
|
||||
if err != nil {
|
||||
return exportedApp, err
|
||||
}
|
||||
|
||||
genesis, err := app.ExportGenesis(ctx, latestHeight)
|
||||
if err != nil {
|
||||
return exportedApp, err
|
||||
}
|
||||
|
||||
readerMap, err := app.Store().StateAt(latestHeight)
|
||||
if err != nil {
|
||||
return exportedApp, err
|
||||
}
|
||||
genesisCtx := services.NewGenesisContext(readerMap)
|
||||
err = genesisCtx.Read(ctx, func(ctx context.Context) error {
|
||||
exportedApp.Validators, err = staking.WriteValidators(ctx, app.StakingKeeper)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return exportedApp, err
|
||||
}
|
||||
|
||||
exportedApp.AppState = genesis
|
||||
exportedApp.Height = int64(latestHeight)
|
||||
if forZeroHeight {
|
||||
height = 0
|
||||
app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs)
|
||||
exportedApp.Height = 0
|
||||
}
|
||||
|
||||
genState, err := app.ModuleManager.ExportGenesis(ctx, app.appCodec)
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, fmt.Errorf("failed to export genesis state: %w", err)
|
||||
}
|
||||
|
||||
appState, err := json.MarshalIndent(genState, "", " ")
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
|
||||
validators, err := staking.WriteValidators(ctx, app.StakingKeeper)
|
||||
return servertypes.ExportedApp{
|
||||
AppState: appState,
|
||||
Validators: validators,
|
||||
Height: height,
|
||||
ConsensusParams: app.BaseApp.GetConsensusParams(ctx),
|
||||
}, err
|
||||
}
|
||||
|
||||
// prepare for fresh start at zero height
|
||||
// NOTE zero height genesis is a temporary feature, which will be deprecated in favor of export at a block height
|
||||
func (app *LaconicApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) {
|
||||
applyAllowedAddrs := false
|
||||
|
||||
// check if there is a allowed address list
|
||||
if len(jailAllowedAddrs) > 0 {
|
||||
applyAllowedAddrs = true
|
||||
}
|
||||
|
||||
allowedAddrsMap := make(map[string]bool)
|
||||
|
||||
for _, addr := range jailAllowedAddrs {
|
||||
_, err := sdk.ValAddressFromBech32(addr)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
allowedAddrsMap[addr] = true
|
||||
}
|
||||
|
||||
/* Handle fee distribution state. */
|
||||
|
||||
// withdraw all validator commission
|
||||
_ = app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
|
||||
valBz, err := app.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, valBz)
|
||||
return false
|
||||
})
|
||||
|
||||
// withdraw all delegator rewards
|
||||
dels, err := app.StakingKeeper.GetAllDelegations(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, delegation := range dels {
|
||||
valAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
delAddr, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// clear validator slash events
|
||||
app.DistrKeeper.DeleteAllValidatorSlashEvents(ctx)
|
||||
|
||||
// clear validator historical rewards
|
||||
app.DistrKeeper.DeleteAllValidatorHistoricalRewards(ctx)
|
||||
|
||||
// set context height to zero
|
||||
height := ctx.BlockHeight()
|
||||
ctx = ctx.WithBlockHeight(0)
|
||||
|
||||
// reinitialize all validators
|
||||
_ = app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
|
||||
valBz, err := app.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// donate any unwithdrawn outstanding reward fraction tokens to the community pool
|
||||
scraps, err := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, valBz)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
feePool, err := app.DistrKeeper.FeePool.Get(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
feePool.CommunityPool = feePool.CommunityPool.Add(scraps...)
|
||||
if err := app.DistrKeeper.FeePool.Set(ctx, feePool); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, valBz); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// reinitialize all delegations
|
||||
for _, del := range dels {
|
||||
valAddr, err := sdk.ValAddressFromBech32(del.ValidatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
delAddr, err := sdk.AccAddressFromBech32(del.DelegatorAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil {
|
||||
// never called as BeforeDelegationCreated always returns nil
|
||||
panic(fmt.Errorf("error while incrementing period: %w", err))
|
||||
}
|
||||
|
||||
if err := app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr); err != nil {
|
||||
// never called as AfterDelegationModified always returns nil
|
||||
panic(fmt.Errorf("error while creating a new delegation period record: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// reset context height
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
|
||||
/* Handle staking state. */
|
||||
|
||||
// iterate through redelegations, reset creation height
|
||||
_ = app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) {
|
||||
for i := range red.Entries {
|
||||
red.Entries[i].CreationHeight = 0
|
||||
}
|
||||
_ = app.StakingKeeper.SetRedelegation(ctx, red)
|
||||
return false
|
||||
})
|
||||
|
||||
// iterate through unbonding delegations, reset creation height
|
||||
_ = app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd stakingtypes.UnbondingDelegation) (stop bool) {
|
||||
for i := range ubd.Entries {
|
||||
ubd.Entries[i].CreationHeight = 0
|
||||
}
|
||||
_ = app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
||||
return false
|
||||
})
|
||||
|
||||
// Iterate through validators by power descending, reset bond heights, and
|
||||
// update bond intra-tx counters.
|
||||
store := ctx.KVStore(app.GetKey(stakingtypes.StoreKey))
|
||||
iter := storetypes.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey)
|
||||
counter := int16(0)
|
||||
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key()))
|
||||
validator, err := app.StakingKeeper.GetValidator(ctx, addr)
|
||||
if errors.Is(err, stakingtypes.ErrNoValidatorFound) {
|
||||
panic("expected validator, not found")
|
||||
} else if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
validator.UnbondingHeight = 0
|
||||
if applyAllowedAddrs && !allowedAddrsMap[addr.String()] {
|
||||
validator.Jailed = true
|
||||
}
|
||||
|
||||
_ = app.StakingKeeper.SetValidator(ctx, validator)
|
||||
counter++
|
||||
}
|
||||
|
||||
if err := iter.Close(); err != nil {
|
||||
app.Logger().Error("error while closing the key-value store reverse prefix iterator: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
/* Handle slashing state. */
|
||||
|
||||
// reset start height on signing infos
|
||||
err = app.SlashingKeeper.IterateValidatorSigningInfos(
|
||||
ctx,
|
||||
func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) {
|
||||
info.StartHeight = 0
|
||||
err = app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return false
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return exportedApp, nil
|
||||
}
|
||||
|
||||
@ -1,14 +1,5 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
"cosmossdk.io/errors"
|
||||
"cosmossdk.io/math"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/address"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
CoinUnit = "lnt"
|
||||
BaseCoinUnit = "alnt"
|
||||
@ -34,43 +25,18 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
SetAddressPrefixes()
|
||||
RegisterDenoms()
|
||||
}
|
||||
|
||||
func RegisterDenoms() {
|
||||
err := sdk.RegisterDenom(CoinUnit, math.LegacyOneDec())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// TODO refactor
|
||||
// err := sdk.RegisterDenom(CoinUnit, math.LegacyOneDec())
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
err = sdk.RegisterDenom(BaseCoinUnit, math.LegacyNewDecWithPrec(1, LntExponent))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func SetAddressPrefixes() {
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(Bech32PrefixAccAddr, Bech32PrefixAccPub)
|
||||
config.SetBech32PrefixForValidator(Bech32PrefixValAddr, Bech32PrefixValPub)
|
||||
config.SetBech32PrefixForConsensusNode(Bech32PrefixConsAddr, Bech32PrefixConsPub)
|
||||
|
||||
// This is copied from the cosmos sdk v0.43.0-beta1
|
||||
// source: https://github.com/cosmos/cosmos-sdk/blob/v0.43.0-beta1/types/address.go#L141
|
||||
config.SetAddressVerifier(func(bytes []byte) error {
|
||||
if len(bytes) == 0 {
|
||||
return errors.Wrap(sdkerrors.ErrUnknownAddress, "addresses cannot be empty")
|
||||
}
|
||||
|
||||
if len(bytes) > address.MaxAddrLen {
|
||||
return errors.Wrapf(sdkerrors.ErrUnknownAddress, "address max length is %d, got %d", address.MaxAddrLen, len(bytes))
|
||||
}
|
||||
|
||||
if len(bytes) != 20 && len(bytes) != 32 {
|
||||
return errors.Wrapf(sdkerrors.ErrUnknownAddress, "address length must be 20 or 32 bytes, got %d", len(bytes))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
// err = sdk.RegisterDenom(BaseCoinUnit, math.LegacyNewDecWithPrec(1, LntExponent))
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
}
|
||||
|
||||
@ -1,71 +1,195 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"cosmossdk.io/client/v2/offchain"
|
||||
coreserver "cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/log"
|
||||
runtimev2 "cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"cosmossdk.io/server/v2/api/grpc"
|
||||
"cosmossdk.io/server/v2/api/rest"
|
||||
"cosmossdk.io/server/v2/api/telemetry"
|
||||
"cosmossdk.io/server/v2/cometbft"
|
||||
serverstore "cosmossdk.io/server/v2/store"
|
||||
confixcmd "cosmossdk.io/tools/confix/cmd"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
"github.com/cosmos/cosmos-sdk/client/debug"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/pruning"
|
||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
"github.com/cosmos/cosmos-sdk/client/snapshot"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
sdktelemetry "github.com/cosmos/cosmos-sdk/telemetry"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
genutilv2cli "github.com/cosmos/cosmos-sdk/x/genutil/v2/cli"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
"git.vdb.to/cerc-io/laconicd/gql"
|
||||
"git.vdb.to/cerc-io/laconicd/server/distsig"
|
||||
"git.vdb.to/cerc-io/laconicd/server/nitro"
|
||||
)
|
||||
|
||||
func initRootCmd(rootCmd *cobra.Command, txConfig client.TxConfig, basicManager module.BasicManager) {
|
||||
// CommandDependencies is a struct that contains all the dependencies needed to initialize the root command.
|
||||
// an alternative design could fetch these even later from the command context
|
||||
type CommandDependencies[T app.Tx] struct {
|
||||
GlobalConfig coreserver.ConfigMap
|
||||
ModuleManager *runtimev2.MM[T]
|
||||
LaconicApp *app.LaconicApp[T]
|
||||
ClientContext client.Context
|
||||
DistSigManager *distsig.Manager
|
||||
// NitroServer *nitro.Server
|
||||
}
|
||||
|
||||
func InitRootCmd[T app.Tx](
|
||||
rootCmd *cobra.Command,
|
||||
logger log.Logger,
|
||||
deps CommandDependencies[T],
|
||||
) (serverv2.ConfigWriter, error) {
|
||||
cfg := sdk.GetConfig()
|
||||
cfg.Seal()
|
||||
|
||||
rootCmd.AddCommand(
|
||||
genutilcli.InitCmd(basicManager, app.DefaultNodeHome),
|
||||
genutilcli.InitCmd(deps.ModuleManager),
|
||||
genesisCommand(deps.ModuleManager, deps.LaconicApp),
|
||||
NewTestnetCmd(deps.ModuleManager),
|
||||
debug.Cmd(),
|
||||
confixcmd.ConfigCommand(),
|
||||
pruning.Cmd(newApp, app.DefaultNodeHome),
|
||||
snapshot.Cmd(newApp),
|
||||
)
|
||||
|
||||
server.AddCommands(rootCmd, app.DefaultNodeHome, newApp, appExport, func(startCmd *cobra.Command) {
|
||||
// Override start command to run the GQL server
|
||||
newStartCmd := server.StartCmdWithOptions(newApp, app.DefaultNodeHome, server.StartCmdOptions{
|
||||
PostSetup: func(svrCtx *server.Context, clientCtx client.Context, ctx context.Context, g *errgroup.Group) error {
|
||||
g.Go(func() error {
|
||||
return gql.Server(ctx, clientCtx, svrCtx.Logger.With("module", "gql-server"))
|
||||
})
|
||||
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
startCmd.RunE = newStartCmd.RunE
|
||||
})
|
||||
|
||||
// add keybase, auxiliary RPC, query, genesis, and tx child commands
|
||||
rootCmd.AddCommand(
|
||||
server.StatusCommand(),
|
||||
genutilcli.Commands(txConfig, basicManager, app.DefaultNodeHome),
|
||||
// add keybase, auxiliary RPC, query, genesis, and tx child commands
|
||||
queryCommand(),
|
||||
txCommand(),
|
||||
keys.Commands(),
|
||||
offchain.OffChain(),
|
||||
)
|
||||
// TODO
|
||||
// pruning.Cmd(newApp),
|
||||
// snapshot.Cmd(newApp),
|
||||
|
||||
// build CLI skeleton for initial config parsing or a client application invocation
|
||||
if deps.LaconicApp == nil {
|
||||
return serverv2.AddCommands[T](
|
||||
rootCmd,
|
||||
logger,
|
||||
io.NopCloser(nil),
|
||||
deps.GlobalConfig,
|
||||
initServerConfig(),
|
||||
cometbft.NewWithConfigOptions[T](initCometConfig()),
|
||||
&grpc.Server[T]{},
|
||||
&serverstore.Server[T]{},
|
||||
&telemetry.Server[T]{},
|
||||
&rest.Server[T]{},
|
||||
// &grpcgateway.Server[T]{},
|
||||
// &swagger.Server[T]{},
|
||||
&gql.Server{},
|
||||
&nitro.Server{},
|
||||
&distsig.Manager{},
|
||||
)
|
||||
}
|
||||
|
||||
// build full app!
|
||||
app := deps.LaconicApp
|
||||
// store component (not a server)
|
||||
storeComponent, err := serverstore.New[T](app.Store(), deps.GlobalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
restServer, err := rest.New(logger, app.App.AppManager, deps.GlobalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// consensus component
|
||||
consensusServer, err := cometbft.New(
|
||||
logger,
|
||||
app.Name(),
|
||||
app.Store(),
|
||||
app.App.AppManager,
|
||||
cometbft.AppCodecs[T]{
|
||||
AppCodec: app.AppCodec(),
|
||||
TxCodec: &client.DefaultTxDecoder[T]{TxConfig: deps.ClientContext.TxConfig},
|
||||
LegacyAmino: deps.ClientContext.LegacyAmino,
|
||||
ConsensusAddressCodec: deps.ClientContext.ConsensusAddressCodec,
|
||||
},
|
||||
app.App.QueryHandlers(),
|
||||
app.App.SchemaDecoderResolver(),
|
||||
initCometOptions[T](app),
|
||||
deps.GlobalConfig,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
telemetryServer, err := telemetry.New[T](logger, sdktelemetry.EnableTelemetry, deps.GlobalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
grpcServer, err := grpc.New[T](
|
||||
logger,
|
||||
app.InterfaceRegistry(),
|
||||
app.QueryHandlers(),
|
||||
app.Query,
|
||||
deps.GlobalConfig,
|
||||
grpc.WithExtraGRPCHandlers[T](
|
||||
consensusServer.GRPCServiceRegistrar(
|
||||
deps.ClientContext,
|
||||
deps.GlobalConfig,
|
||||
),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlServer, err := gql.New(logger, deps.GlobalConfig, deps.ClientContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nitroServer, err := nitro.NewServer(logger, deps.GlobalConfig, deps.ClientContext.Keyring)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// wire server commands
|
||||
return serverv2.AddCommands[T](
|
||||
rootCmd,
|
||||
logger,
|
||||
app,
|
||||
deps.GlobalConfig,
|
||||
initServerConfig(),
|
||||
consensusServer,
|
||||
grpcServer,
|
||||
storeComponent,
|
||||
telemetryServer,
|
||||
restServer,
|
||||
gqlServer,
|
||||
deps.DistSigManager,
|
||||
nitroServer,
|
||||
)
|
||||
}
|
||||
|
||||
// genesisCommand builds genesis-related `simd genesis` command.
|
||||
func genesisCommand[T app.Tx](
|
||||
moduleManager *runtimev2.MM[T],
|
||||
app *app.LaconicApp[T],
|
||||
) *cobra.Command {
|
||||
var genTxValidator func([]transaction.Msg) error
|
||||
if moduleManager != nil {
|
||||
genTxValidator = moduleManager.Modules()[genutiltypes.ModuleName].(genutil.AppModule).GenTxValidator()
|
||||
}
|
||||
cmd := genutilv2cli.Commands(
|
||||
genTxValidator,
|
||||
moduleManager,
|
||||
app,
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func queryCommand() *cobra.Command {
|
||||
@ -79,12 +203,11 @@ func queryCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
rpc.ValidatorCommand(),
|
||||
server.QueryBlockCmd(),
|
||||
cometbft.QueryBlockCmd(),
|
||||
cometbft.QueryBlocksCmd(),
|
||||
cometbft.QueryBlockResultsCmd(),
|
||||
authcmd.QueryTxsByEventsCmd(),
|
||||
server.QueryBlocksCmd(),
|
||||
authcmd.QueryTxCmd(),
|
||||
server.QueryBlockResultsCmd(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
@ -114,64 +237,29 @@ func txCommand() *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// newApp is an appCreator
|
||||
func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
|
||||
baseappOptions := server.DefaultBaseappOptions(appOpts)
|
||||
app, err := app.NewLaconicApp(logger, db, traceStore, true, appOpts, baseappOptions...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
func RootCommandPersistentPreRun(clientCtx client.Context) func(*cobra.Command, []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
// set the default command outputs
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
cmd.SetErr(cmd.ErrOrStderr())
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// appExport creates a new app (optionally at a given height) and exports state.
|
||||
func appExport(
|
||||
logger log.Logger,
|
||||
db dbm.DB,
|
||||
traceStore io.Writer,
|
||||
height int64,
|
||||
forZeroHeight bool,
|
||||
jailAllowedAddrs []string,
|
||||
appOpts servertypes.AppOptions,
|
||||
modulesToExport []string,
|
||||
) (servertypes.ExportedApp, error) {
|
||||
var (
|
||||
laconicApp *app.LaconicApp
|
||||
err error
|
||||
)
|
||||
|
||||
// this check is necessary as we use the flag in x/upgrade.
|
||||
// we can exit more gracefully by checking the flag here.
|
||||
homePath, ok := appOpts.Get(flags.FlagHome).(string)
|
||||
if !ok || homePath == "" {
|
||||
return servertypes.ExportedApp{}, errors.New("application home not set")
|
||||
}
|
||||
|
||||
viperAppOpts, ok := appOpts.(*viper.Viper)
|
||||
if !ok {
|
||||
return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper")
|
||||
}
|
||||
|
||||
// overwrite the FlagInvCheckPeriod
|
||||
viperAppOpts.Set(server.FlagInvCheckPeriod, 1)
|
||||
appOpts = viperAppOpts
|
||||
|
||||
if height != -1 {
|
||||
laconicApp, err = app.NewLaconicApp(logger, db, traceStore, false, appOpts)
|
||||
clientCtx = clientCtx.WithCmdContext(cmd.Context())
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
return err
|
||||
}
|
||||
|
||||
if err := laconicApp.LoadHeight(height); err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
} else {
|
||||
laconicApp, err = app.NewLaconicApp(logger, db, traceStore, true, appOpts)
|
||||
customClientTemplate, customClientConfig := initClientConfig()
|
||||
clientCtx, err = config.CreateClientConfig(
|
||||
clientCtx, customClientTemplate, customClientConfig)
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return laconicApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport)
|
||||
if err = client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
78
cmd/laconicd/cmd/config.go
Normal file
78
cmd/laconicd/cmd/config.go
Normal file
@ -0,0 +1,78 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
cmtcfg "github.com/cometbft/cometbft/config"
|
||||
|
||||
"cosmossdk.io/core/transaction"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"cosmossdk.io/server/v2/cometbft"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
)
|
||||
|
||||
// initAppConfig helps to override default client config template and configs.
|
||||
// return "", nil if no custom configuration is required for the application.
|
||||
func initClientConfig() (string, interface{}) {
|
||||
// customClientConfigTemplate, customClientConfig
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Allow the chain developer to overwrite the server default app toml config.
|
||||
func initServerConfig() serverv2.ServerConfig {
|
||||
serverCfg := serverv2.DefaultServerConfig()
|
||||
serverCfg.MinGasPrices = "0" + sdk.DefaultBondDenom
|
||||
// The server's default minimum gas price is set to "0stake" inside
|
||||
// app.toml. However, the chain developer can set a default app.toml value for their
|
||||
// validators here. Please update value based on chain denom.
|
||||
//
|
||||
// In summary:
|
||||
// - if you set serverCfg.MinGasPrices value, validators CAN tweak their
|
||||
// own app.toml to override, or use this default value.
|
||||
//
|
||||
// In simapp, we set the min gas prices to 0.
|
||||
// serverCfg.MinGasPrices = "0stake"
|
||||
|
||||
return serverCfg
|
||||
}
|
||||
|
||||
// initCometConfig helps to override default comet config template and configs.
|
||||
func initCometConfig() cometbft.CfgOption {
|
||||
cfg := cmtcfg.DefaultConfig()
|
||||
|
||||
// display only warn logs by default except for p2p and state
|
||||
// better default logging
|
||||
cfg.LogLevel = "*:warn,server:info,p2p:info,state:info"
|
||||
cfg.LogLevel += ",auction:info,bond:info,registry:info,gql-server:info"
|
||||
// increase block timeout
|
||||
cfg.Consensus.TimeoutCommit = 3 * time.Second
|
||||
// overwrite default pprof listen address
|
||||
cfg.RPC.PprofListenAddress = "localhost:6060"
|
||||
// use previous db backend
|
||||
cfg.DBBackend = "goleveldb"
|
||||
|
||||
return cometbft.OverwriteDefaultConfigTomlConfig(cfg)
|
||||
}
|
||||
|
||||
func initCometOptions[T transaction.Tx](laconic *app.LaconicApp[T]) cometbft.ServerOptions[T] {
|
||||
serverOptions := cometbft.DefaultServerOptions[T]()
|
||||
// Implement custom handlers (e.g. for Vote Extensions)
|
||||
// serverOptions.PrepareProposalHandler = CustomPrepareProposal[T]()
|
||||
// serverOptions.ProcessProposalHandler = CustomProcessProposalHandler[T]()
|
||||
serverOptions.ExtendVoteHandler = laconic.ExtendVote
|
||||
serverOptions.VerifyVoteExtensionHandler = laconic.VerifyVoteExtension
|
||||
|
||||
// overwrite app mempool, using max-txs option
|
||||
// serverOptions.Mempool = func(cfg map[string]any) mempool.Mempool[T] {
|
||||
// if maxTxs := cast.ToInt(cfg[cometbft.FlagMempoolMaxTxs]); maxTxs >= 0 {
|
||||
// return sdkmempool.NewSenderNonceMempool(
|
||||
// sdkmempool.SenderNonceMaxTxOpt(maxTxs),
|
||||
// )
|
||||
// }
|
||||
// return mempool.NoOpMempool[T]{}
|
||||
// }
|
||||
|
||||
return serverOptions
|
||||
}
|
||||
70
cmd/laconicd/cmd/depinject.go
Normal file
70
cmd/laconicd/cmd/depinject.go
Normal file
@ -0,0 +1,70 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"cosmossdk.io/core/address"
|
||||
runtime "cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/server/nitro"
|
||||
)
|
||||
|
||||
func ProvideClientContext(
|
||||
configMap runtime.GlobalConfig,
|
||||
appCodec codec.Codec,
|
||||
interfaceRegistry codectypes.InterfaceRegistry,
|
||||
txConfig client.TxConfig,
|
||||
// legacyAmino registry.AminoRegistrar,
|
||||
addressCodec address.Codec,
|
||||
validatorAddressCodec address.ValidatorAddressCodec,
|
||||
consensusAddressCodec address.ConsensusAddressCodec,
|
||||
) client.Context {
|
||||
var err error
|
||||
homeDir, ok := configMap[serverv2.FlagHome].(string)
|
||||
if !ok {
|
||||
panic("server.ConfigMap must contain a string value for serverv2.FlagHome")
|
||||
}
|
||||
|
||||
clientCtx := client.Context{}.
|
||||
WithCodec(appCodec).
|
||||
WithInterfaceRegistry(interfaceRegistry).
|
||||
WithTxConfig(txConfig).
|
||||
// WithLegacyAmino(amino).
|
||||
WithInput(os.Stdin).
|
||||
WithAccountRetriever(types.AccountRetriever{}).
|
||||
WithAddressCodec(addressCodec).
|
||||
WithValidatorAddressCodec(validatorAddressCodec).
|
||||
WithConsensusAddressCodec(consensusAddressCodec).
|
||||
WithHomeDir(homeDir).
|
||||
WithViper(EnvPrefix) // env variable prefix
|
||||
|
||||
// Read the config to overwrite the default values with the values from the config file
|
||||
customClientTemplate, customClientConfig := initClientConfig()
|
||||
clientCtx, err = config.CreateClientConfig(clientCtx, customClientTemplate, customClientConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// // Workaround: Unset clientCtx.HomeDir and clientCtx.KeyringDir from depinject clientCtx as they
|
||||
// // are given precedence over the CLI args (--home flag) in some commands
|
||||
// // TODO: Implement proper fix
|
||||
// clientCtx.HomeDir = ""
|
||||
// clientCtx.KeyringDir = ""
|
||||
|
||||
return clientCtx
|
||||
}
|
||||
|
||||
func ProvideKeyring(clientCtx client.Context) keyring.Keyring {
|
||||
return clientCtx.Keyring
|
||||
}
|
||||
|
||||
func ProvideNitroService(configMap runtime.GlobalConfig) (nitro.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
94
cmd/laconicd/cmd/log.go
Normal file
94
cmd/laconicd/cmd/log.go
Normal file
@ -0,0 +1,94 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/log"
|
||||
sdk_slog "cosmossdk.io/log/slog"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"github.com/lmittmann/tint"
|
||||
)
|
||||
|
||||
// TODO stderr logger?
|
||||
|
||||
func newSlogLogger(cfg server.ConfigMap, out io.Writer) (log.Logger, error) {
|
||||
handler, err := newSlogHandler(cfg, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sdk_slog.NewCustomLogger(slog.New(handler)), nil
|
||||
}
|
||||
|
||||
// newSlogHandler creates a slog handler based on the server configuration.
|
||||
func newSlogHandler(cfg server.ConfigMap, out io.Writer) (slog.Handler, error) {
|
||||
var (
|
||||
format string
|
||||
noColor bool
|
||||
trace bool
|
||||
level string
|
||||
)
|
||||
if v, ok := cfg[serverv2.FlagLogFormat]; ok {
|
||||
format = v.(string)
|
||||
}
|
||||
if v, ok := cfg[serverv2.FlagLogNoColor]; ok {
|
||||
noColor = v.(bool)
|
||||
}
|
||||
if v, ok := cfg[serverv2.FlagTrace]; ok {
|
||||
trace = v.(bool)
|
||||
}
|
||||
if v, ok := cfg[serverv2.FlagLogLevel]; ok {
|
||||
level = v.(string)
|
||||
}
|
||||
_ = trace
|
||||
|
||||
logLvl, err := parseSlogLevel(level)
|
||||
if err != nil {
|
||||
// If the log level is not a valid zerolog level, then we try to parse it as a key filter.
|
||||
filterFunc, err := log.ParseLogLevel(level, parseSlogLevel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = log.NewFilterWriter(out, filterFunc)
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
// if json format is requested, ignore no_color
|
||||
if format == serverv2.OutputFormatJSON {
|
||||
handler = slog.NewJSONHandler(out, &slog.HandlerOptions{
|
||||
Level: logLvl,
|
||||
})
|
||||
} else {
|
||||
handler = tint.NewHandler(out, &tint.Options{
|
||||
Level: logLvl,
|
||||
TimeFormat: time.Kitchen,
|
||||
NoColor: noColor,
|
||||
})
|
||||
}
|
||||
return handler, nil
|
||||
}
|
||||
|
||||
func parseSlogLevel(l string) (slog.Level, error) {
|
||||
// Legal log level values are hardcoded into server/v2 command factory:
|
||||
// (trace|debug|info|warn|error|fatal|panic|disabled or '*:<level>,<key>:<level>')
|
||||
// however, slog only has debug, info, warn, error
|
||||
switch l {
|
||||
case "debug", "trace":
|
||||
return slog.LevelDebug, nil
|
||||
case "info":
|
||||
return slog.LevelInfo, nil
|
||||
case "warn":
|
||||
return slog.LevelWarn, nil
|
||||
case "error":
|
||||
return slog.LevelError, nil
|
||||
case "fatal", "panic":
|
||||
return slog.LevelError, nil
|
||||
case "disabled":
|
||||
return slog.Level(math.MaxInt), nil
|
||||
}
|
||||
return 0, fmt.Errorf("invalid log level: %s", l)
|
||||
}
|
||||
@ -1,161 +1,132 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"errors"
|
||||
|
||||
cmtcfg "github.com/cometbft/cometbft/config"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"cosmossdk.io/client/v2/autocli"
|
||||
clientv2keyring "cosmossdk.io/client/v2/autocli/keyring"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
runtime "cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
"git.vdb.to/cerc-io/laconicd/gql"
|
||||
"git.vdb.to/cerc-io/laconicd/server/distsig"
|
||||
)
|
||||
|
||||
const EnvPrefix = "LACONIC"
|
||||
const (
|
||||
// EnvPrefix is the environment variable prefix for the application
|
||||
EnvPrefix = "LACONIC"
|
||||
|
||||
// NewRootCmd creates a new root command for laconicd. It is called once in the
|
||||
// main function.
|
||||
func NewRootCmd() *cobra.Command {
|
||||
var (
|
||||
txConfigOpts tx.ConfigOptions
|
||||
autoCliOpts autocli.AppOptions
|
||||
moduleBasicManager module.BasicManager
|
||||
clientCtx client.Context
|
||||
// DefaultNodeHome is the default data directory name for the application
|
||||
DefaultNodeHome = ".laconicd"
|
||||
)
|
||||
|
||||
func NewRootCmd[T app.Tx](
|
||||
args ...string,
|
||||
) (*cobra.Command, error) {
|
||||
rootCommand := &cobra.Command{
|
||||
Use: "laconicd",
|
||||
SilenceErrors: true,
|
||||
}
|
||||
configWriter, err := InitRootCmd(rootCommand, log.NewNopLogger(), CommandDependencies[T]{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
factory, err := serverv2.NewCommandFactory(
|
||||
serverv2.WithConfigWriter(configWriter),
|
||||
serverv2.WithStdDefaultHomeDir(DefaultNodeHome),
|
||||
serverv2.WithLoggerFactory(serverv2.NewLogger),
|
||||
// serverv2.WithLoggerFactory(newSlogLogger),
|
||||
)
|
||||
|
||||
if err := depinject.Inject(
|
||||
depinject.Configs(app.AppConfig(),
|
||||
depinject.Supply(
|
||||
log.NewNopLogger(),
|
||||
),
|
||||
depinject.Provide(
|
||||
ProvideClientContext,
|
||||
ProvideKeyring,
|
||||
),
|
||||
),
|
||||
&txConfigOpts,
|
||||
&autoCliOpts,
|
||||
&moduleBasicManager,
|
||||
&clientCtx,
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "laconicd",
|
||||
Short: "Laconic Daemon",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
|
||||
// set the default command outputs
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
cmd.SetErr(cmd.ErrOrStderr())
|
||||
|
||||
clientCtx = clientCtx.WithCmdContext(cmd.Context()).WithViper(EnvPrefix)
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientCtx, err = config.ReadFromClientConfig(clientCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// sign mode textual is only available in online mode
|
||||
if !clientCtx.Offline {
|
||||
// This needs to go after ReadFromClientConfig, as that function ets the RPC client needed for SIGN_MODE_TEXTUAL.
|
||||
txConfigOpts.EnabledSignModes = append(txConfigOpts.EnabledSignModes, signing.SignMode_SIGN_MODE_TEXTUAL)
|
||||
txConfigOpts.TextualCoinMetadataQueryFn = txmodule.NewGRPCCoinMetadataQueryFn(clientCtx)
|
||||
txConfigWithTextual, err := tx.NewTxConfigWithOptions(codec.NewProtoCodec(clientCtx.InterfaceRegistry), txConfigOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientCtx = clientCtx.WithTxConfig(txConfigWithTextual)
|
||||
}
|
||||
|
||||
if err := client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// overwrite the minimum gas price from the app configuration
|
||||
srvCfg := serverconfig.DefaultConfig()
|
||||
srvCfg.MinGasPrices = fmt.Sprintf("0%s", sdk.DefaultBondDenom)
|
||||
|
||||
// overwrite the block timeout
|
||||
cmtCfg := cmtcfg.DefaultConfig()
|
||||
cmtCfg.Consensus.TimeoutCommit = 3 * time.Second
|
||||
cmtCfg.LogLevel = "*:error,p2p:info,state:info,auction:info,bond:info,registry:info,gql-server:info" // better default logging
|
||||
|
||||
return server.InterceptConfigsPreRunHandler(cmd, serverconfig.DefaultConfigTemplate, srvCfg, cmtCfg)
|
||||
},
|
||||
}
|
||||
|
||||
initRootCmd(rootCmd, clientCtx.TxConfig, moduleBasicManager)
|
||||
|
||||
if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Add flags for GQL server.
|
||||
rootCmd = gql.AddGQLFlags(rootCmd)
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
func ProvideClientContext(
|
||||
appCodec codec.Codec,
|
||||
interfaceRegistry codectypes.InterfaceRegistry,
|
||||
txConfig client.TxConfig,
|
||||
legacyAmino *codec.LegacyAmino,
|
||||
) client.Context {
|
||||
clientCtx := client.Context{}.
|
||||
WithCodec(appCodec).
|
||||
WithInterfaceRegistry(interfaceRegistry).
|
||||
WithTxConfig(txConfig).
|
||||
WithLegacyAmino(legacyAmino).
|
||||
WithInput(os.Stdin).
|
||||
WithAccountRetriever(types.AccountRetriever{}).
|
||||
WithHomeDir(app.DefaultNodeHome).
|
||||
WithViper(EnvPrefix) // env variable prefix
|
||||
|
||||
// Read the config again to overwrite the default values with the values from the config file
|
||||
clientCtx, _ = config.ReadFromClientConfig(clientCtx)
|
||||
|
||||
// Workaround: Unset clientCtx.HomeDir and clientCtx.KeyringDir from depinject clientCtx as they are given precedence over
|
||||
// the CLI args (--home flag) in some commands
|
||||
// TODO: Implement proper fix
|
||||
clientCtx.HomeDir = ""
|
||||
clientCtx.KeyringDir = ""
|
||||
|
||||
return clientCtx
|
||||
}
|
||||
|
||||
func ProvideKeyring(clientCtx client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) {
|
||||
kb, err := client.NewKeyringFromBackend(clientCtx, clientCtx.Keyring.Backend())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return keyring.NewAutoCLIKeyring(kb)
|
||||
var autoCliOpts autocli.AppOptions
|
||||
if err := depinject.Inject(
|
||||
depinject.Configs(
|
||||
app.AppConfig(),
|
||||
depinject.Supply(runtime.GlobalConfig{}, log.NewNopLogger())),
|
||||
&autoCliOpts,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = autoCliOpts.EnhanceRootCommand(rootCommand); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subCommand, configMap, logger, err := factory.ParseCommand(rootCommand, args)
|
||||
if err != nil {
|
||||
if errors.Is(err, pflag.ErrHelp) {
|
||||
return rootCommand, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
moduleManager *runtime.MM[T]
|
||||
clientCtx client.Context
|
||||
laconic *app.LaconicApp[T]
|
||||
dsManager *distsig.Manager
|
||||
// nitroServer *nitro.Server
|
||||
depinjectConfig = depinject.Configs(
|
||||
depinject.Supply(logger, runtime.GlobalConfig(configMap)),
|
||||
depinject.Provide(
|
||||
ProvideClientContext,
|
||||
ProvideKeyring,
|
||||
),
|
||||
)
|
||||
)
|
||||
if serverv2.IsAppRequired(subCommand) {
|
||||
// server construction
|
||||
laconic, err = app.NewLaconicApp[T](
|
||||
depinjectConfig,
|
||||
&autoCliOpts, &moduleManager, &clientCtx, &dsManager,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// client construction
|
||||
if err = depinject.Inject(
|
||||
depinject.Configs(
|
||||
app.AppConfig(),
|
||||
depinjectConfig,
|
||||
),
|
||||
&autoCliOpts, &moduleManager, &clientCtx, &dsManager,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
commandDeps := CommandDependencies[T]{
|
||||
GlobalConfig: configMap,
|
||||
ModuleManager: moduleManager,
|
||||
LaconicApp: laconic,
|
||||
ClientContext: clientCtx,
|
||||
DistSigManager: dsManager,
|
||||
// NitroServer: nitroServer,
|
||||
}
|
||||
rootCommand = &cobra.Command{
|
||||
Use: "laconicd",
|
||||
Short: "Laconic Daemon",
|
||||
SilenceErrors: true,
|
||||
PersistentPreRunE: RootCommandPersistentPreRun(clientCtx),
|
||||
}
|
||||
factory.EnhanceRootCommand(rootCommand)
|
||||
_, err = InitRootCmd(rootCommand, logger, commandDeps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := autoCliOpts.EnhanceRootCommand(rootCommand); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rootCommand, nil
|
||||
}
|
||||
|
||||
67
cmd/laconicd/cmd/root_test.go
Normal file
67
cmd/laconicd/cmd/root_test.go
Normal file
@ -0,0 +1,67 @@
|
||||
package cmd_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
"git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd"
|
||||
)
|
||||
|
||||
func TestInitCmd(t *testing.T) {
|
||||
args := []string{
|
||||
"init", // Test the init cmd
|
||||
"laconicd-test", // Moniker
|
||||
fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists
|
||||
}
|
||||
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
|
||||
require.NoError(t, err)
|
||||
rootCmd.SetArgs(args)
|
||||
require.NoError(t, rootCmd.Execute())
|
||||
}
|
||||
|
||||
func TestHomeFlagRegistration(t *testing.T) {
|
||||
homeDir := "/tmp/foo"
|
||||
args := []string{
|
||||
"query",
|
||||
fmt.Sprintf("--%s", flags.FlagHome),
|
||||
homeDir,
|
||||
}
|
||||
|
||||
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
|
||||
require.NoError(t, err)
|
||||
rootCmd.SetArgs(args)
|
||||
require.NoError(t, rootCmd.Execute())
|
||||
|
||||
result, err := rootCmd.Flags().GetString(flags.FlagHome)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, homeDir)
|
||||
}
|
||||
|
||||
func TestHelpRequested(t *testing.T) {
|
||||
argz := [][]string{
|
||||
{"query", "--help"},
|
||||
{"query", "tx", "-h"},
|
||||
{"--help"},
|
||||
{"start", "-h"},
|
||||
}
|
||||
|
||||
for _, args := range argz {
|
||||
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
|
||||
require.NoError(t, err)
|
||||
|
||||
var out bytes.Buffer
|
||||
rootCmd.SetArgs(args)
|
||||
rootCmd.SetOut(&out)
|
||||
require.NoError(t, rootCmd.Execute())
|
||||
require.Contains(t, out.String(), args[0])
|
||||
require.Contains(t, out.String(), "--help")
|
||||
require.Contains(t, out.String(), "Usage:")
|
||||
}
|
||||
}
|
||||
490
cmd/laconicd/cmd/testnet.go
Normal file
490
cmd/laconicd/cmd/testnet.go
Normal file
@ -0,0 +1,490 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
cmtconfig "github.com/cometbft/cometbft/config"
|
||||
cmttime "github.com/cometbft/cometbft/types/time"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/math/unsafe"
|
||||
runtimev2 "cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"cosmossdk.io/server/v2/api/grpc"
|
||||
"cosmossdk.io/server/v2/cometbft"
|
||||
"cosmossdk.io/server/v2/store"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
var (
|
||||
flagNodeDirPrefix = "node-dir-prefix"
|
||||
flagNumValidators = "validator-count"
|
||||
flagOutputDir = "output-dir"
|
||||
flagNodeDaemonHome = "node-daemon-home"
|
||||
flagStartingIPAddress = "starting-ip-address"
|
||||
flagListenIPAddress = "listen-ip-address"
|
||||
flagStakingDenom = "staking-denom"
|
||||
flagCommitTimeout = "commit-timeout"
|
||||
flagSingleHost = "single-host"
|
||||
)
|
||||
|
||||
type initArgs struct {
|
||||
algo string
|
||||
chainID string
|
||||
keyringBackend string
|
||||
minGasPrices string
|
||||
nodeDaemonHome string
|
||||
nodeDirPrefix string
|
||||
numValidators int
|
||||
outputDir string
|
||||
startingIPAddress string
|
||||
listenIPAddress string
|
||||
singleMachine bool
|
||||
bondTokenDenom string
|
||||
}
|
||||
|
||||
func addTestnetFlagsToCmd(cmd *cobra.Command) {
|
||||
cmd.Flags().IntP(flagNumValidators, "n", 4, "Number of validators to initialize the testnet with")
|
||||
cmd.Flags().StringP(flagOutputDir, "o", "./.testnets", "Directory to store initialization data for the testnet")
|
||||
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
|
||||
cmd.Flags().String(serverv2.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)")
|
||||
cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
|
||||
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix for the name of per-validator subdirectories (to be number-suffixed like node0, node1, ...)")
|
||||
cmd.Flags().String(flagNodeDaemonHome, "laconicd", "Home directory of the node's daemon configuration")
|
||||
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
||||
cmd.Flags().String(flagListenIPAddress, "127.0.0.1", "TCP or UNIX socket IP address for the RPC server to listen on")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
|
||||
cmd.Flags().Duration(flagCommitTimeout, 5*time.Second, "Time to wait after a block commit before starting on the new height")
|
||||
cmd.Flags().Bool(flagSingleHost, false, "Cluster runs on a single host machine with different ports")
|
||||
cmd.Flags().String(flagStakingDenom, sdk.DefaultBondDenom, "Default staking token denominator")
|
||||
}
|
||||
|
||||
// NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize
|
||||
// validator configuration files for running a multi-validator testnet in a separate process
|
||||
func NewTestnetCmd[T transaction.Tx](mm *runtimev2.MM[T]) *cobra.Command {
|
||||
testnetCmd := &cobra.Command{
|
||||
Use: "testnet",
|
||||
Short: "subcommands for starting or configuring local testnets",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
testnetCmd.AddCommand(testnetInitFilesCmd(mm))
|
||||
|
||||
return testnetCmd
|
||||
}
|
||||
|
||||
// testnetInitFilesCmd returns a cmd to initialize all files for CometBFT testnet and application
|
||||
func testnetInitFilesCmd[T transaction.Tx](mm *runtimev2.MM[T]) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "init-files",
|
||||
Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)",
|
||||
Long: fmt.Sprintf(`init-files will setup one directory per validator and populate each with
|
||||
necessary files (private validator, genesis, config, etc.) for running validator nodes.
|
||||
|
||||
Booting up a network with these validator folders is intended to be used with Docker Compose,
|
||||
or a similar setup where each node has a manually configurable IP address.
|
||||
|
||||
Note, strict routability for addresses is turned off in the config file.
|
||||
|
||||
Example:
|
||||
%s testnet init-files --validator-count 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2
|
||||
`, version.AppName),
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := client.GetConfigFromCmd(cmd)
|
||||
|
||||
args := initArgs{}
|
||||
args.outputDir, _ = cmd.Flags().GetString(flagOutputDir)
|
||||
args.keyringBackend, _ = cmd.Flags().GetString(flags.FlagKeyringBackend)
|
||||
args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID)
|
||||
args.minGasPrices, _ = cmd.Flags().GetString(serverv2.FlagMinGasPrices)
|
||||
args.nodeDirPrefix, _ = cmd.Flags().GetString(flagNodeDirPrefix)
|
||||
args.nodeDaemonHome, _ = cmd.Flags().GetString(flagNodeDaemonHome)
|
||||
args.startingIPAddress, _ = cmd.Flags().GetString(flagStartingIPAddress)
|
||||
args.listenIPAddress, _ = cmd.Flags().GetString(flagListenIPAddress)
|
||||
args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators)
|
||||
args.algo, _ = cmd.Flags().GetString(flags.FlagKeyType)
|
||||
args.bondTokenDenom, _ = cmd.Flags().GetString(flagStakingDenom)
|
||||
args.singleMachine, _ = cmd.Flags().GetBool(flagSingleHost)
|
||||
config.Consensus.TimeoutCommit, err = cmd.Flags().GetDuration(flagCommitTimeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return initTestnetFiles(clientCtx, cmd, config, mm, args)
|
||||
},
|
||||
}
|
||||
|
||||
addTestnetFlagsToCmd(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
const nodeDirPerm = 0o755
|
||||
|
||||
// initTestnetFiles initializes testnet files for a testnet to be run in a separate process
|
||||
func initTestnetFiles[T transaction.Tx](
|
||||
clientCtx client.Context,
|
||||
cmd *cobra.Command,
|
||||
nodeConfig *cmtconfig.Config,
|
||||
mm *runtimev2.MM[T],
|
||||
args initArgs,
|
||||
) error {
|
||||
if args.chainID == "" {
|
||||
args.chainID = "chain-" + unsafe.Str(6)
|
||||
}
|
||||
nodeIDs := make([]string, args.numValidators)
|
||||
valPubKeys := make([]cryptotypes.PubKey, args.numValidators)
|
||||
|
||||
var (
|
||||
genAccounts []authtypes.GenesisAccount
|
||||
genBalances []banktypes.Balance
|
||||
genFiles []string
|
||||
)
|
||||
const (
|
||||
rpcPort = 26657
|
||||
apiPort = 1317
|
||||
grpcPort = 9090
|
||||
)
|
||||
p2pPortStart := 26656
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
// generate private keys, node IDs, and initial transactions
|
||||
for i := 0; i < args.numValidators; i++ {
|
||||
var portOffset int
|
||||
grpcConfig := grpc.DefaultConfig()
|
||||
if args.singleMachine {
|
||||
portOffset = i
|
||||
p2pPortStart = 16656 // use different start point to not conflict with rpc port
|
||||
nodeConfig.P2P.AddrBookStrict = false
|
||||
nodeConfig.P2P.PexReactor = false
|
||||
nodeConfig.P2P.AllowDuplicateIP = true
|
||||
|
||||
grpcConfig = &grpc.Config{
|
||||
Enable: true,
|
||||
Address: fmt.Sprintf("127.0.0.1:%d", grpcPort+portOffset),
|
||||
MaxRecvMsgSize: grpc.DefaultConfig().MaxRecvMsgSize,
|
||||
MaxSendMsgSize: grpc.DefaultConfig().MaxSendMsgSize,
|
||||
}
|
||||
}
|
||||
|
||||
nodeDirName := fmt.Sprintf("%s%d", args.nodeDirPrefix, i)
|
||||
nodeDir := filepath.Join(args.outputDir, nodeDirName, args.nodeDaemonHome)
|
||||
cmd.Println("Node dir", nodeDir)
|
||||
gentxsDir := filepath.Join(args.outputDir, "gentxs")
|
||||
|
||||
nodeConfig.SetRoot(nodeDir)
|
||||
nodeConfig.Moniker = nodeDirName
|
||||
nodeConfig.RPC.ListenAddress = fmt.Sprintf("tcp://%s:%d", args.listenIPAddress, rpcPort+portOffset)
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
var (
|
||||
err error
|
||||
ip string
|
||||
)
|
||||
if args.singleMachine {
|
||||
ip = "127.0.0.1"
|
||||
} else {
|
||||
ip, err = getIP(i, args.startingIPAddress)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig, args.algo)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
memo := fmt.Sprintf("%s@%s:%d", nodeIDs[i], ip, p2pPortStart+portOffset)
|
||||
genFiles = append(genFiles, nodeConfig.GenesisFile())
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf, clientCtx.Codec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(args.algo, keyringAlgos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, secret, err := testutil.GenerateSaveCoinKey(kb, nodeDirName, "", true, algo, sdk.GetFullBIP44Path())
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(args.outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
info := map[string]string{"secret": secret}
|
||||
|
||||
cliPrint, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save private key seed words
|
||||
if err := writeFile(fmt.Sprintf("%v.json", "key_seed"), nodeDir, cliPrint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accTokens := sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction)
|
||||
accStakingTokens := sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction)
|
||||
coins := sdk.Coins{
|
||||
sdk.NewCoin("testtoken", accTokens),
|
||||
sdk.NewCoin(args.bondTokenDenom, accStakingTokens),
|
||||
}
|
||||
|
||||
addrStr, err := clientCtx.AddressCodec.BytesToString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: use x/accounts?
|
||||
genBalances = append(genBalances, banktypes.Balance{Address: addrStr, Coins: coins.Sort()})
|
||||
genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0))
|
||||
|
||||
valStr, err := clientCtx.ValidatorAddressCodec.BytesToString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valTokens := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction)
|
||||
createValMsg, err := stakingtypes.NewMsgCreateValidator(
|
||||
valStr,
|
||||
valPubKeys[i],
|
||||
sdk.NewCoin(args.bondTokenDenom, valTokens),
|
||||
stakingtypes.NewDescription(nodeDirName, "", "", "", "", &stakingtypes.Metadata{}),
|
||||
stakingtypes.NewCommissionRates(math.LegacyOneDec(), math.LegacyOneDec(), math.LegacyOneDec()),
|
||||
math.OneInt(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBuilder := clientCtx.TxConfig.NewTxBuilder()
|
||||
if err := txBuilder.SetMsgs(createValMsg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBuilder.SetMemo(memo)
|
||||
txBuilder.SetGasLimit(flags.DefaultGasLimit)
|
||||
txBuilder.SetFeePayer(addr)
|
||||
|
||||
txFactory := tx.Factory{}
|
||||
txFactory = txFactory.
|
||||
WithChainID(args.chainID).
|
||||
WithMemo(memo).
|
||||
WithKeybase(kb).
|
||||
WithTxConfig(clientCtx.TxConfig)
|
||||
|
||||
if err := tx.Sign(clientCtx, txFactory, nodeDirName, txBuilder, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serverCfg := serverv2.DefaultServerConfig()
|
||||
serverCfg.MinGasPrices = args.minGasPrices
|
||||
|
||||
cometServer := cometbft.NewWithConfigOptions[T](cometbft.OverwriteDefaultConfigTomlConfig(nodeConfig))
|
||||
storeServer := &store.Server[T]{}
|
||||
grpcServer := grpc.NewWithConfigOptions[T](grpc.OverwriteDefaultConfig(grpcConfig))
|
||||
server := serverv2.NewServer[T](serverCfg, cometServer, storeServer, grpcServer)
|
||||
err = server.WriteConfig(filepath.Join(nodeDir, "config"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := initGenFiles(clientCtx, mm, args.chainID, genAccounts, genBalances, genFiles, args.numValidators); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := collectGenFiles(
|
||||
clientCtx, nodeConfig, args.chainID, nodeIDs, valPubKeys, args.numValidators,
|
||||
args.outputDir, args.nodeDirPrefix, args.nodeDaemonHome,
|
||||
rpcPort, p2pPortStart, args.singleMachine,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update viper root
|
||||
serverv2.GetViperFromCmd(cmd).Set(flags.FlagHome, nodeConfig.RootDir)
|
||||
|
||||
cmd.PrintErrf("Successfully initialized %d node directories\n", args.numValidators)
|
||||
return nil
|
||||
}
|
||||
|
||||
func initGenFiles[T transaction.Tx](
|
||||
clientCtx client.Context, mm *runtimev2.MM[T], chainID string,
|
||||
genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance,
|
||||
genFiles []string, numValidators int,
|
||||
) error {
|
||||
appGenState := mm.DefaultGenesis()
|
||||
|
||||
// set the accounts in the genesis state
|
||||
var authGenState authtypes.GenesisState
|
||||
clientCtx.Codec.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState)
|
||||
|
||||
accounts, err := authtypes.PackAccounts(genAccounts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authGenState.Accounts = accounts
|
||||
appGenState[authtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&authGenState)
|
||||
|
||||
// set the balances in the genesis state
|
||||
var bankGenState banktypes.GenesisState
|
||||
clientCtx.Codec.MustUnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState)
|
||||
|
||||
bankGenState.Balances, err = banktypes.SanitizeGenesisBalances(genBalances, clientCtx.AddressCodec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, bal := range bankGenState.Balances {
|
||||
bankGenState.Supply = bankGenState.Supply.Add(bal.Coins...)
|
||||
}
|
||||
appGenState[banktypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&bankGenState)
|
||||
|
||||
appGenStateJSON, err := json.MarshalIndent(appGenState, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appGenesis := genutiltypes.NewAppGenesisWithVersion(chainID, appGenStateJSON)
|
||||
// generate empty genesis files for each validator and save
|
||||
for i := 0; i < numValidators; i++ {
|
||||
if err := appGenesis.SaveAs(genFiles[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectGenFiles(
|
||||
clientCtx client.Context, nodeConfig *cmtconfig.Config, chainID string,
|
||||
nodeIDs []string, valPubKeys []cryptotypes.PubKey, numValidators int,
|
||||
outputDir, nodeDirPrefix, nodeDaemonHome string,
|
||||
rpcPortStart, p2pPortStart int,
|
||||
singleMachine bool,
|
||||
) error {
|
||||
var appState json.RawMessage
|
||||
genTime := cmttime.Now()
|
||||
|
||||
for i := 0; i < numValidators; i++ {
|
||||
if singleMachine {
|
||||
portOffset := i
|
||||
nodeConfig.RPC.ListenAddress = fmt.Sprintf("tcp://127.0.0.1:%d", rpcPortStart+portOffset)
|
||||
nodeConfig.P2P.ListenAddress = fmt.Sprintf("tcp://127.0.0.1:%d", p2pPortStart+portOffset)
|
||||
}
|
||||
|
||||
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
|
||||
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
|
||||
gentxsDir := filepath.Join(outputDir, "gentxs")
|
||||
nodeConfig.Moniker = nodeDirName
|
||||
|
||||
nodeConfig.SetRoot(nodeDir)
|
||||
|
||||
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
|
||||
initCfg := genutiltypes.NewInitConfig(chainID, gentxsDir, nodeID, valPubKey)
|
||||
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(nodeConfig.GenesisFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeAppState, err := genutil.GenAppStateFromConfig(clientCtx.Codec, clientCtx.TxConfig, nodeConfig, initCfg, appGenesis, genutiltypes.DefaultMessageValidator,
|
||||
clientCtx.ValidatorAddressCodec, clientCtx.AddressCodec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if appState == nil {
|
||||
// set the canonical application state (they should not differ)
|
||||
appState = nodeAppState
|
||||
}
|
||||
|
||||
genFile := nodeConfig.GenesisFile()
|
||||
|
||||
// overwrite each validator's genesis file to have a canonical genesis time
|
||||
if err := genutil.ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIP(i int, startingIPAddr string) (ip string, err error) {
|
||||
if len(startingIPAddr) == 0 {
|
||||
ip, err = serverv2.ExternalIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
return calculateIP(startingIPAddr, i)
|
||||
}
|
||||
|
||||
func calculateIP(ip string, i int) (string, error) {
|
||||
ipv4 := net.ParseIP(ip).To4()
|
||||
if ipv4 == nil {
|
||||
return "", fmt.Errorf("%v: non ipv4 address", ip)
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
ipv4[3]++
|
||||
}
|
||||
|
||||
return ipv4.String(), nil
|
||||
}
|
||||
|
||||
func writeFile(name, dir string, contents []byte) error {
|
||||
file := filepath.Join(dir, name)
|
||||
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return fmt.Errorf("could not create directory %q: %w", dir, err)
|
||||
}
|
||||
|
||||
return os.WriteFile(file, contents, 0o600)
|
||||
}
|
||||
26
cmd/laconicd/cmd/testnet_test.go
Normal file
26
cmd/laconicd/cmd/testnet_test.go
Normal file
@ -0,0 +1,26 @@
|
||||
package cmd_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
"git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd"
|
||||
)
|
||||
|
||||
func TestInitTestFilesCmd(t *testing.T) {
|
||||
args := []string{
|
||||
"testnet", // Test the testnet init-files command
|
||||
"init-files",
|
||||
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest), // Set keyring-backend to test
|
||||
}
|
||||
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
|
||||
require.NoError(t, err)
|
||||
rootCmd.SetArgs(args)
|
||||
require.NoError(t, rootCmd.Execute())
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
"git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd"
|
||||
)
|
||||
|
||||
func TestInitCmd(t *testing.T) {
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd.SetArgs([]string{
|
||||
"init", // Test the init cmd
|
||||
"localtestnet", // Moniker
|
||||
fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, "laconic_9000-1"),
|
||||
})
|
||||
|
||||
err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@ -1,22 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
"git.vdb.to/cerc-io/laconicd/app/params"
|
||||
"git.vdb.to/cerc-io/laconicd/cmd/laconicd/cmd"
|
||||
|
||||
_ "git.vdb.to/cerc-io/laconicd/app/params" // import for side-effects
|
||||
)
|
||||
|
||||
func main() {
|
||||
params.SetAddressPrefixes()
|
||||
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil {
|
||||
fmt.Fprintln(rootCmd.OutOrStderr(), err)
|
||||
// reproduce default cobra behavior so that eager parsing of flags is possible.
|
||||
// see: https://github.com/spf13/cobra/blob/e94f6d0dd9a5e5738dca6bce03c4b1207ffbc0ec/command.go#L1082
|
||||
args := os.Args[1:]
|
||||
rootCmd, err := cmd.NewRootCmd[app.Tx](args...)
|
||||
if err != nil {
|
||||
if _, pErr := fmt.Fprintln(os.Stderr, err); pErr != nil {
|
||||
panic(errors.Join(err, pErr))
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
if err = rootCmd.Execute(); err != nil {
|
||||
if _, pErr := fmt.Fprintln(rootCmd.OutOrStderr(), err); pErr != nil {
|
||||
panic(errors.Join(err, pErr))
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
372
go.mod
372
go.mod
@ -1,10 +1,11 @@
|
||||
module git.vdb.to/cerc-io/laconicd
|
||||
|
||||
go 1.21
|
||||
go 1.23.5
|
||||
|
||||
toolchain go1.21.0
|
||||
toolchain go1.23.6
|
||||
|
||||
replace (
|
||||
github.com/ethereum/go-ethereum => ../mod/go-ethereum
|
||||
// Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
|
||||
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
|
||||
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
|
||||
@ -13,190 +14,339 @@ replace (
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/api v0.7.2
|
||||
cosmossdk.io/client/v2 v2.0.0-beta.1
|
||||
cosmossdk.io/collections v0.4.0
|
||||
cosmossdk.io/core v0.11.0
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4
|
||||
cosmossdk.io/api v0.8.2
|
||||
cosmossdk.io/client/v2 v2.0.0-beta.6
|
||||
cosmossdk.io/collections v1.1.0
|
||||
cosmossdk.io/core v1.0.0
|
||||
cosmossdk.io/depinject v1.1.0
|
||||
cosmossdk.io/errors v1.0.1
|
||||
cosmossdk.io/log v1.3.0
|
||||
cosmossdk.io/math v1.2.0
|
||||
cosmossdk.io/store v1.0.2
|
||||
cosmossdk.io/log v1.5.0
|
||||
cosmossdk.io/math v1.5.0
|
||||
cosmossdk.io/runtime/v2 v2.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/server/v2 v2.0.0-beta.1
|
||||
cosmossdk.io/server/v2/cometbft v0.0.0-20241017154543-c1707b830856
|
||||
cosmossdk.io/store v1.10.0-rc.1
|
||||
cosmossdk.io/store/v2 v2.0.0-beta.1
|
||||
cosmossdk.io/tools/confix v0.1.0
|
||||
git.vdb.to/cerc-io/chainsig v0.1.0
|
||||
github.com/99designs/gqlgen v0.17.22
|
||||
github.com/cometbft/cometbft v0.38.2
|
||||
github.com/cosmos/cosmos-db v1.0.0
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3
|
||||
github.com/cosmos/cosmos-sdk v0.50.3
|
||||
github.com/cometbft/cometbft v1.0.1
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.5
|
||||
github.com/cosmos/cosmos-sdk v1.0.0
|
||||
github.com/cosmos/go-bip39 v1.0.0
|
||||
github.com/cosmos/gogoproto v1.4.11
|
||||
github.com/cosmos/gogoproto v1.7.0
|
||||
github.com/deckarep/golang-set v1.8.0
|
||||
github.com/ethereum/go-ethereum v1.14.5
|
||||
github.com/ethereum/go-ethereum v1.14.13
|
||||
github.com/gibson042/canonicaljson-go v1.0.3
|
||||
github.com/go-chi/chi/v5 v5.0.8
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/ipfs/go-cid v0.4.1
|
||||
github.com/ipld/go-ipld-prime v0.21.0
|
||||
github.com/rs/cors v1.8.3
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.17.0
|
||||
github.com/statechannels/go-nitro v0.1.2
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/lmittmann/tint v1.0.7
|
||||
github.com/rs/cors v1.11.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/pflag v1.0.6
|
||||
github.com/statechannels/go-nitro v0.2.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/tidwall/gjson v1.14.4
|
||||
github.com/tidwall/sjson v1.2.5
|
||||
github.com/vektah/gqlparser/v2 v2.5.11
|
||||
golang.org/x/sync v0.7.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f
|
||||
google.golang.org/grpc v1.60.1
|
||||
google.golang.org/protobuf v1.33.0
|
||||
go.dedis.ch/kyber/v3 v3.1.0
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a
|
||||
google.golang.org/grpc v1.70.0
|
||||
google.golang.org/protobuf v1.36.4
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/x/tx v0.13.0 // indirect
|
||||
filippo.io/edwards25519 v1.0.0 // indirect
|
||||
cosmossdk.io/systemtests v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/accounts v1.0.0-alpha.4
|
||||
cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91
|
||||
cosmossdk.io/x/consensus v0.0.0-20241007000829-38662ecb209f
|
||||
cosmossdk.io/x/distribution v0.0.0-20241007000829-38662ecb209f
|
||||
cosmossdk.io/x/gov v1.0.0-alpha.4
|
||||
cosmossdk.io/x/mint v0.0.0-20241004153623-489aaae40234
|
||||
cosmossdk.io/x/protocolpool v1.0.0-alpha.4
|
||||
cosmossdk.io/x/slashing v0.0.0-20241007000829-38662ecb209f
|
||||
cosmossdk.io/x/staking v1.0.0-alpha.4
|
||||
github.com/cometbft/cometbft/api v1.0.0
|
||||
github.com/spf13/viper v1.19.0
|
||||
)
|
||||
|
||||
require (
|
||||
buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.36.4-20241120201313-68e42a58b301.1 // indirect
|
||||
buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.36.4-20240130113600-88ef6483f90f.1 // indirect
|
||||
cosmossdk.io/core/testing v0.0.2 // indirect
|
||||
cosmossdk.io/errors/v2 v2.0.0 // indirect
|
||||
cosmossdk.io/schema v1.0.0 // indirect
|
||||
cosmossdk.io/server/v2/appmanager v1.0.0-beta.2 // indirect
|
||||
cosmossdk.io/server/v2/stf v1.0.0-beta.2 // indirect
|
||||
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect
|
||||
cosmossdk.io/x/tx v1.1.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/99designs/keyring v1.2.2 // indirect
|
||||
github.com/DataDog/datadog-go v4.8.3+incompatible // indirect
|
||||
github.com/DataDog/zstd v1.5.6 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.10.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
|
||||
github.com/bgentry/speakeasy v0.2.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/bvinc/go-sqlite-lite v0.6.1 // indirect
|
||||
github.com/bytedance/sonic v1.12.8 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
|
||||
github.com/cockroachdb/errors v1.11.1 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||
github.com/cockroachdb/pebble v1.1.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
|
||||
github.com/cockroachdb/errors v1.11.3 // indirect
|
||||
github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 // indirect
|
||||
github.com/cockroachdb/pebble v1.1.4 // indirect
|
||||
github.com/cockroachdb/redact v1.1.5 // indirect
|
||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
github.com/cometbft/cometbft-db v0.9.1 // indirect
|
||||
github.com/cometbft/cometbft-db v1.0.2 // indirect
|
||||
github.com/consensys/bavard v0.1.13 // indirect
|
||||
github.com/consensys/gnark-crypto v0.12.1 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/gogogateway v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v1.0.0 // indirect
|
||||
github.com/cosmos/ics23/go v0.10.0 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
|
||||
github.com/creachadair/atomicfile v0.3.1 // indirect
|
||||
github.com/creachadair/tomledit v0.0.24 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/cosmos/cosmos-db v1.1.1 // indirect
|
||||
github.com/cosmos/iavl v1.3.5 // indirect
|
||||
github.com/cosmos/iavl/v2 v2.0.0-alpha.4 // indirect
|
||||
github.com/cosmos/ics23/go v0.11.0 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
|
||||
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
|
||||
github.com/creachadair/atomicfile v0.3.7 // indirect
|
||||
github.com/creachadair/tomledit v0.0.27 // indirect
|
||||
github.com/danieljoos/wincred v1.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/dgraph-io/badger/v4 v4.5.1 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/emicklei/dot v1.6.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.25.0 // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
|
||||
github.com/emicklei/dot v1.6.2 // indirect
|
||||
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
|
||||
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.31.1 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/flatbuffers v25.1.24+incompatible // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||
github.com/hashicorp/go-bexpr v0.1.10 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-metrics v0.5.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.5.2 // indirect
|
||||
github.com/hashicorp/go-metrics v0.5.4 // indirect
|
||||
github.com/hashicorp/go-plugin v1.6.3 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
|
||||
github.com/holiman/uint256 v1.2.4 // indirect
|
||||
github.com/huandu/skiplist v1.2.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
|
||||
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
||||
github.com/holiman/uint256 v1.3.1 // indirect
|
||||
github.com/huandu/skiplist v1.2.1 // indirect
|
||||
github.com/huin/goupnp v1.3.0 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/improbable-eng/grpc-web v0.15.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/kocubinski/costor-api v1.1.1 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/linxGnu/grocksdb v1.8.6 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/libp2p/go-libp2p v0.37.0 // indirect
|
||||
github.com/linxGnu/grocksdb v1.9.8 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mdp/qrterminal/v3 v3.2.0 // indirect
|
||||
github.com/minio/highwayhash v1.0.3 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||
github.com/mmcloughlin/addchain v0.4.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||
github.com/multiformats/go-multiaddr v0.13.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||
github.com/multiformats/go-multicodec v0.9.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-varint v0.0.7 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/gomega v1.34.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/polydawn/refmt v0.89.0 // indirect
|
||||
github.com/prometheus/client_golang v1.17.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/rs/zerolog v1.31.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.5 // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/spf13/afero v1.10.0 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/supranational/blst v0.3.13 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tidwall/btree v1.7.0 // indirect
|
||||
github.com/tidwall/buntdb v1.2.10 // indirect
|
||||
github.com/tidwall/grect v0.1.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/rtred v0.1.2 // indirect
|
||||
github.com/tidwall/tinyqueue v0.1.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/urfave/cli/v2 v2.25.7 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/zondax/hid v0.9.2 // indirect
|
||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.8 // indirect
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
|
||||
go.dedis.ch/fixbuf v1.0.3 // indirect
|
||||
go.dedis.ch/protobuf v1.0.11 // indirect
|
||||
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
golang.org/x/arch v0.13.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/term v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250122153221-138b5a5a4fd4 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
lukechampine.com/blake3 v1.2.1 // indirect
|
||||
nhooyr.io/websocket v1.8.6 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
pgregory.net/rapid v1.1.0 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
rsc.io/qr v0.2.0 // indirect
|
||||
rsc.io/tmplfunc v0.0.3 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/statechannels/go-nitro v0.1.2 => github.com/cerc-io/go-nitro v0.1.3-ts-port-0.1.10
|
||||
replace (
|
||||
git.vdb.to/cerc-io/chainsig => ../mod/chainsig
|
||||
// github.com/statechannels/go-nitro v0.1.2 => github.com/cerc-io/go-nitro v0.1.3-ts-port-0.1.10
|
||||
github.com/statechannels/go-nitro => ../mod/go-nitro
|
||||
)
|
||||
|
||||
// replace (
|
||||
// cosmossdk.io/core v0.7.6 => github.com/roysc/cosmos-sdk/core v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/api v0.7.6 => github.com/roysc/cosmos-sdk/api v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/client/v2 => github.com/roysc/cosmos-sdk/client/v2 v2.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/store => github.com/roysc/cosmos-sdk/store v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/x/bank => github.com/roysc/cosmos-sdk/x/bank v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/x/mint => github.com/roysc/cosmos-sdk/x/mint v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/x/gov => github.com/roysc/cosmos-sdk/x/gov v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/x/staking => github.com/roysc/cosmos-sdk/x/staking v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/x/tx => github.com/roysc/cosmos-sdk/x/tx v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// cosmossdk.io/x/epochs => github.com/roysc/cosmos-sdk/x/epochs v0.0.0-20241001191620-a3729c1ad6ba
|
||||
// github.com/cosmos/cosmos-sdk => github.com/roysc/cosmos-sdk v1.0.0-dev
|
||||
// )
|
||||
|
||||
// dev
|
||||
replace (
|
||||
// cosmossdk.io/core => ../mod/cosmos-sdk/core
|
||||
cosmossdk.io/api => ../mod/cosmos-sdk/api
|
||||
cosmossdk.io/client/v2 => ../mod/cosmos-sdk/client/v2
|
||||
cosmossdk.io/core/testing => ../mod/cosmos-sdk/core/testing
|
||||
cosmossdk.io/depinject => ../mod/cosmos-sdk/depinject
|
||||
cosmossdk.io/log => ../mod/cosmos-sdk/log
|
||||
cosmossdk.io/runtime/v2 => ../mod/cosmos-sdk/runtime/v2
|
||||
cosmossdk.io/server/v2 => ../mod/cosmos-sdk/server/v2
|
||||
cosmossdk.io/server/v2/appmanager => ../mod/cosmos-sdk/server/v2/appmanager
|
||||
cosmossdk.io/server/v2/cometbft => ../mod/cosmos-sdk/server/v2/cometbft
|
||||
cosmossdk.io/server/v2/stf => ../mod/cosmos-sdk/server/v2/stf
|
||||
cosmossdk.io/store => ../mod/cosmos-sdk/store
|
||||
cosmossdk.io/store/v2 => ../mod/cosmos-sdk/store/v2
|
||||
cosmossdk.io/systemtests => ../mod/cosmos-sdk/systemtests
|
||||
cosmossdk.io/tools/confix => ../mod/cosmos-sdk/tools/confix
|
||||
)
|
||||
|
||||
replace (
|
||||
cosmossdk.io/x/accounts => ../mod/cosmos-sdk/x/accounts
|
||||
cosmossdk.io/x/accounts/defaults/base => ../mod/cosmos-sdk/x/accounts/defaults/base
|
||||
cosmossdk.io/x/accounts/defaults/lockup => ../mod/cosmos-sdk/x/accounts/defaults/lockup
|
||||
cosmossdk.io/x/accounts/defaults/multisig => ../mod/cosmos-sdk/x/accounts/defaults/multisig
|
||||
cosmossdk.io/x/bank => ../mod/cosmos-sdk/x/bank
|
||||
cosmossdk.io/x/consensus => ../mod/cosmos-sdk/x/consensus
|
||||
cosmossdk.io/x/distribution => ../mod/cosmos-sdk/x/distribution
|
||||
cosmossdk.io/x/epochs => ../mod/cosmos-sdk/x/epochs
|
||||
cosmossdk.io/x/gov => ../mod/cosmos-sdk/x/gov
|
||||
cosmossdk.io/x/mint => ../mod/cosmos-sdk/x/mint
|
||||
cosmossdk.io/x/params => ../mod/cosmos-sdk/x/params
|
||||
cosmossdk.io/x/protocolpool => ../mod/cosmos-sdk/x/protocolpool
|
||||
cosmossdk.io/x/slashing => ../mod/cosmos-sdk/x/slashing
|
||||
cosmossdk.io/x/staking => ../mod/cosmos-sdk/x/staking
|
||||
cosmossdk.io/x/tx => ../mod/cosmos-sdk/x/tx
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/cometbft/cometbft => ../mod/cometbft
|
||||
// github.com/cometbft/cometbft/api => ../mod/cometbft/api
|
||||
github.com/cosmos/cosmos-sdk => ../mod/cosmos-sdk
|
||||
go.dedis.ch/kyber/v3 => ../mod/kyber
|
||||
)
|
||||
|
||||
// replace google.golang.org/protobuf => /Users/roy/clone/protobuf-go
|
||||
|
||||
@ -29,7 +29,7 @@ On having some change in the GQL schema (for example: adding a new query) update
|
||||
## Start server
|
||||
|
||||
```shell
|
||||
laconicd start --gql-playground --gql-server
|
||||
laconicd start --gql.playground --gql.server
|
||||
```
|
||||
|
||||
Basic node status:
|
||||
|
||||
19
gql/config.go
Normal file
19
gql/config.go
Normal file
@ -0,0 +1,19 @@
|
||||
package gql
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Enable: false,
|
||||
Playground: false,
|
||||
PlaygroundAPIBase: "",
|
||||
Port: 9473,
|
||||
// LogFile: "",
|
||||
}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Enable bool `mapstructure:"enable" toml:"enable" comment:"Enable the GraphQL server."`
|
||||
Playground bool `mapstructure:"playground" toml:"playground" comment:"Enable the GraphQL playground."`
|
||||
PlaygroundAPIBase string `mapstructure:"playground-api-base" toml:"playground-api-base" comment:"GraphQL API base path to use in the playground."`
|
||||
Port uint `mapstructure:"port" toml:"port" comment:"Port to use for the GraphQL server."`
|
||||
// LogFile string `mapstructure:"log-file" toml:"log-file" comment:"File to tail for the 'getLogs' API."`
|
||||
}
|
||||
29
gql/flags.go
29
gql/flags.go
@ -1,15 +1,24 @@
|
||||
package gql
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
import "github.com/spf13/pflag"
|
||||
|
||||
// AddGQLFlags adds gql flags for
|
||||
func AddGQLFlags(cmd *cobra.Command) *cobra.Command {
|
||||
// Add flags for GQL server.
|
||||
cmd.PersistentFlags().Bool("gql-server", false, "Start GQL server.")
|
||||
cmd.PersistentFlags().Bool("gql-playground", false, "Enable GQL playground.")
|
||||
cmd.PersistentFlags().String("gql-playground-api-base", "", "GQL API base path to use in GQL playground.")
|
||||
cmd.PersistentFlags().String("gql-port", "9473", "Port to use for the GQL server.")
|
||||
cmd.PersistentFlags().String("log-file", "", "File to tail for GQL 'getLogs' API.")
|
||||
var (
|
||||
FlagEnable = prefix("enable")
|
||||
FlagPlayground = prefix("playground")
|
||||
FlagPlaygroundAPIBase = prefix("playground-api-base")
|
||||
FlagPort = prefix("port")
|
||||
//FlagLogFile = prefix("log-file")
|
||||
)
|
||||
|
||||
return cmd
|
||||
// AddGQLFlags adds flags for the GraphQL server.
|
||||
func AddGQLFlags(flags *pflag.FlagSet) {
|
||||
flags.Bool(FlagEnable, false, "Enable the GraphQL server")
|
||||
flags.Bool(FlagPlayground, false, "Enable the GraphQL playground")
|
||||
flags.String(FlagPlaygroundAPIBase, "", "GraphQL API base path to use in the playground")
|
||||
flags.String(FlagPort, "9473", "Port to use for the GraphQL server.")
|
||||
// cmd.PersistentFlags().String(FlagLogFile, "", "File to tail for GraphQL 'getLogs' API")
|
||||
}
|
||||
|
||||
func prefix(f string) string {
|
||||
return ServerName + "." + f
|
||||
}
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
schema:
|
||||
- cerc-io/laconicd/*.graphql
|
||||
exec:
|
||||
filename: generated.go
|
||||
filename: schema/generated.go
|
||||
model:
|
||||
filename: models_gen.go
|
||||
filename: schema/models_gen.go
|
||||
resolver:
|
||||
filename: resolver.go
|
||||
type: Resolver
|
||||
@ -14,4 +14,4 @@ resolver:
|
||||
models:
|
||||
Link:
|
||||
model:
|
||||
- git.vdb.to/cerc-io/laconicd/gql.Link
|
||||
- git.vdb.to/cerc-io/laconicd/gql/schema.Link
|
||||
|
||||
@ -6,12 +6,14 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
"git.vdb.to/cerc-io/laconicd/utils"
|
||||
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
onboardingTypes "git.vdb.to/cerc-io/laconicd/x/onboarding"
|
||||
@ -33,13 +35,13 @@ type Resolver struct {
|
||||
}
|
||||
|
||||
// Query is the entry point to query execution.
|
||||
func (r *Resolver) Query() QueryResolver {
|
||||
func (r *Resolver) Query() schema.QueryResolver {
|
||||
return &queryResolver{r}
|
||||
}
|
||||
|
||||
type queryResolver struct{ *Resolver }
|
||||
|
||||
func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*Authority, error) {
|
||||
func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*schema.Authority, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
|
||||
@ -53,14 +55,14 @@ func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*Au
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authorities := make([]*Authority, len(authoritiesResp.GetAuthorities()))
|
||||
authorities := make([]*schema.Authority, len(authoritiesResp.GetAuthorities()))
|
||||
for i, a := range authoritiesResp.Authorities {
|
||||
entry, err := getAuthorityRecord(*a.Entry, auctionQueryClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authorities[i] = &Authority{
|
||||
authorities[i] = &schema.Authority{
|
||||
Name: a.Name,
|
||||
Entry: entry,
|
||||
}
|
||||
@ -69,10 +71,10 @@ func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*Au
|
||||
return authorities, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*AuthorityRecord, error) {
|
||||
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*schema.AuthorityRecord, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
gqlResponse := []*AuthorityRecord{}
|
||||
gqlResponse := []*schema.AuthorityRecord{}
|
||||
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.Whois(context.Background(), ®istrytypes.QueryWhoisRequest{Name: name})
|
||||
@ -97,9 +99,9 @@ func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*Record, error) {
|
||||
func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*schema.Record, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*Record
|
||||
var gqlResponse []*schema.Record
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.ResolveLrn(context.Background(), ®istrytypes.QueryResolveLrnRequest{Lrn: name})
|
||||
if err != nil {
|
||||
@ -118,9 +120,9 @@ func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*Rec
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*NameRecord, error) {
|
||||
func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*schema.NameRecord, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*NameRecord
|
||||
var gqlResponse []*schema.NameRecord
|
||||
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.LookupLrn(context.Background(), ®istrytypes.QueryLookupLrnRequest{Lrn: name})
|
||||
@ -140,7 +142,7 @@ func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*Name
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueInput, all *bool, limit *int, offset *int) ([]*Record, error) {
|
||||
func (q queryResolver) QueryRecords(ctx context.Context, attributes []*schema.KeyValueInput, all *bool, limit *int, offset *int) ([]*schema.Record, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
|
||||
var pagination *query.PageRequest
|
||||
@ -175,7 +177,7 @@ func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueI
|
||||
}
|
||||
|
||||
records := res.GetRecords()
|
||||
gqlResponse := make([]*Record, len(records))
|
||||
gqlResponse := make([]*schema.Record, len(records))
|
||||
|
||||
for i, record := range records {
|
||||
gqlRecord, err := getGQLRecord(context.Background(), q, record)
|
||||
@ -188,9 +190,9 @@ func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueI
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Record, error) {
|
||||
func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*schema.Record, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
gqlResponse := make([]*Record, len(ids))
|
||||
gqlResponse := make([]*schema.Record, len(ids))
|
||||
|
||||
for i, id := range ids {
|
||||
res, err := nsQueryClient.GetRecord(context.Background(), ®istrytypes.QueryGetRecordRequest{Id: id})
|
||||
@ -209,7 +211,7 @@ func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Re
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||
func (q queryResolver) GetStatus(ctx context.Context) (*schema.Status, error) {
|
||||
nodeInfo, syncInfo, validatorInfo, err := getStatusInfo(q.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -230,7 +232,7 @@ func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Status{
|
||||
return &schema.Status{
|
||||
Version: RegistryVersion,
|
||||
Node: nodeInfo,
|
||||
Sync: syncInfo,
|
||||
@ -242,8 +244,8 @@ func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*Account, error) {
|
||||
accounts := make([]*Account, len(addresses))
|
||||
func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*schema.Account, error) {
|
||||
accounts := make([]*schema.Account, len(addresses))
|
||||
for index, address := range addresses {
|
||||
account, err := q.GetAccount(ctx, address)
|
||||
if err != nil {
|
||||
@ -254,7 +256,7 @@ func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account, error) {
|
||||
func (q queryResolver) GetAccount(ctx context.Context, address string) (*schema.Account, error) {
|
||||
authQueryClient := authtypes.NewQueryClient(q.ctx)
|
||||
accountResponse, err := authQueryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: address})
|
||||
if err != nil {
|
||||
@ -280,7 +282,7 @@ func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account
|
||||
accNum := strconv.FormatUint(account.GetAccountNumber(), 10)
|
||||
seq := strconv.FormatUint(account.GetSequence(), 10)
|
||||
|
||||
return &Account{
|
||||
return &schema.Account{
|
||||
Address: address,
|
||||
Number: accNum,
|
||||
Sequence: seq,
|
||||
@ -289,8 +291,8 @@ func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*Bond, error) {
|
||||
bonds := make([]*Bond, len(ids))
|
||||
func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*schema.Bond, error) {
|
||||
bonds := make([]*schema.Bond, len(ids))
|
||||
for index, id := range ids {
|
||||
bondObj, err := q.GetBond(ctx, id)
|
||||
if err != nil {
|
||||
@ -302,7 +304,7 @@ func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*Bond
|
||||
return bonds, nil
|
||||
}
|
||||
|
||||
func (q *queryResolver) GetBond(ctx context.Context, id string) (*Bond, error) {
|
||||
func (q *queryResolver) GetBond(ctx context.Context, id string) (*schema.Bond, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bondResp, err := bondQueryClient.GetBondById(context.Background(), &bondtypes.QueryGetBondByIdRequest{Id: id})
|
||||
if err != nil {
|
||||
@ -320,14 +322,14 @@ func (q *queryResolver) GetBond(ctx context.Context, id string) (*Bond, error) {
|
||||
return getGQLBond(bondResp.GetBond())
|
||||
}
|
||||
|
||||
func (q queryResolver) QueryBonds(ctx context.Context) ([]*Bond, error) {
|
||||
func (q queryResolver) QueryBonds(ctx context.Context) ([]*schema.Bond, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bonds, err := bondQueryClient.Bonds(context.Background(), &bondtypes.QueryBondsRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlResponse := make([]*Bond, len(bonds.GetBonds()))
|
||||
gqlResponse := make([]*schema.Bond, len(bonds.GetBonds()))
|
||||
for i, bondObj := range bonds.GetBonds() {
|
||||
gqlBond, err := getGQLBond(bondObj)
|
||||
if err != nil {
|
||||
@ -340,8 +342,8 @@ func (q queryResolver) QueryBonds(ctx context.Context) ([]*Bond, error) {
|
||||
}
|
||||
|
||||
// QueryBondsByOwner will return bonds by owner
|
||||
func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []string) ([]*OwnerBonds, error) {
|
||||
ownerBonds := make([]*OwnerBonds, len(ownerAddresses))
|
||||
func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []string) ([]*schema.OwnerBonds, error) {
|
||||
ownerBonds := make([]*schema.OwnerBonds, len(ownerAddresses))
|
||||
for index, ownerAddress := range ownerAddresses {
|
||||
bondsObj, err := q.GetBondsByOwner(ctx, ownerAddress)
|
||||
if err != nil {
|
||||
@ -353,14 +355,14 @@ func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []s
|
||||
return ownerBonds, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*OwnerBonds, error) {
|
||||
func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*schema.OwnerBonds, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bondResp, err := bondQueryClient.GetBondsByOwner(context.Background(), &bondtypes.QueryGetBondsByOwnerRequest{Owner: address})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ownerBonds := make([]*Bond, len(bondResp.GetBonds()))
|
||||
ownerBonds := make([]*schema.Bond, len(bondResp.GetBonds()))
|
||||
for i, bond := range bondResp.GetBonds() {
|
||||
// #nosec G601
|
||||
bondObj, err := getGQLBond(&bond) //nolint: all
|
||||
@ -370,12 +372,12 @@ func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*Ow
|
||||
ownerBonds[i] = bondObj
|
||||
}
|
||||
|
||||
return &OwnerBonds{Bonds: ownerBonds, Owner: address}, nil
|
||||
return &schema.OwnerBonds{Bonds: ownerBonds, Owner: address}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*Auction, error) {
|
||||
func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*schema.Auction, error) {
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
gqlAuctionResponse := make([]*Auction, len(ids))
|
||||
gqlAuctionResponse := make([]*schema.Auction, len(ids))
|
||||
for i, id := range ids {
|
||||
auctionObj, err := auctionQueryClient.GetAuction(context.Background(), &auctiontypes.QueryGetAuctionRequest{Id: id})
|
||||
if err != nil {
|
||||
@ -397,18 +399,22 @@ func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*A
|
||||
return gqlAuctionResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetParticipants(ctx context.Context) ([]*Participant, error) {
|
||||
func (q queryResolver) GetParticipants(ctx context.Context) ([]*schema.Participant, error) {
|
||||
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
||||
participantResp, err := onboardingQueryClient.Participants(context.Background(), &onboardingTypes.QueryParticipantsRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
participants := make([]*Participant, len(participantResp.GetParticipants()))
|
||||
participants := make([]*schema.Participant, len(participantResp.GetParticipants()))
|
||||
for i, p := range participantResp.Participants {
|
||||
participants[i] = &Participant{
|
||||
nitroAddress, err := utils.EthAddressFromPubKey(p.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
participants[i] = &schema.Participant{
|
||||
CosmosAddress: p.CosmosAddress,
|
||||
NitroAddress: p.NitroAddress,
|
||||
NitroAddress: nitroAddress.String(),
|
||||
Role: p.Role,
|
||||
KycID: p.KycId,
|
||||
}
|
||||
@ -417,7 +423,7 @@ func (q queryResolver) GetParticipants(ctx context.Context) ([]*Participant, err
|
||||
return participants, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetParticipantByAddress(ctx context.Context, address string) (*Participant, error) {
|
||||
func (q queryResolver) GetParticipantByAddress(ctx context.Context, address string) (*schema.Participant, error) {
|
||||
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
||||
participantResp, err := onboardingQueryClient.GetParticipantByAddress(ctx, &onboardingTypes.QueryGetParticipantByAddressRequest{Address: address})
|
||||
if err != nil {
|
||||
@ -425,9 +431,13 @@ func (q queryResolver) GetParticipantByAddress(ctx context.Context, address stri
|
||||
}
|
||||
|
||||
p := participantResp.Participant
|
||||
participant := &Participant{
|
||||
nitroAddress, err := utils.EthAddressFromPubKey(p.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
participant := &schema.Participant{
|
||||
CosmosAddress: p.CosmosAddress,
|
||||
NitroAddress: p.NitroAddress,
|
||||
NitroAddress: nitroAddress.String(),
|
||||
Role: p.Role,
|
||||
KycID: p.KycId,
|
||||
}
|
||||
@ -435,7 +445,7 @@ func (q queryResolver) GetParticipantByAddress(ctx context.Context, address stri
|
||||
return participant, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAddress string) (*Participant, error) {
|
||||
func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAddress string) (*schema.Participant, error) {
|
||||
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
||||
participantResp, err := onboardingQueryClient.GetParticipantByNitroAddress(
|
||||
ctx,
|
||||
@ -448,9 +458,9 @@ func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAd
|
||||
}
|
||||
|
||||
p := participantResp.Participant
|
||||
participant := &Participant{
|
||||
participant := &schema.Participant{
|
||||
CosmosAddress: p.CosmosAddress,
|
||||
NitroAddress: p.NitroAddress,
|
||||
NitroAddress: nitroAddress,
|
||||
Role: p.Role,
|
||||
KycID: p.KycId,
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
package gql
|
||||
package schema
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||
|
||||
package gql
|
||||
package schema
|
||||
|
||||
type Value interface {
|
||||
IsValue()
|
||||
128
gql/server.go
128
gql/server.go
@ -2,74 +2,124 @@ package gql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/log"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/cors"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// Server configures and starts the GQL server.
|
||||
func Server(ctx context.Context, clientCtx client.Context, logger log.Logger) error {
|
||||
if !viper.GetBool("gql-server") {
|
||||
return nil
|
||||
const (
|
||||
ServerName = "gql"
|
||||
)
|
||||
|
||||
var (
|
||||
_ serverv2.ServerComponent[transaction.Tx] = (*Server)(nil)
|
||||
_ serverv2.HasStartFlags = (*Server)(nil)
|
||||
_ serverv2.HasConfig = (*Server)(nil)
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
logger log.Logger
|
||||
router chi.Router
|
||||
config *Config
|
||||
httpServer *http.Server
|
||||
}
|
||||
|
||||
func New(logger log.Logger, cfg server.ConfigMap, clientCtx client.Context) (*Server, error) {
|
||||
s := &Server{
|
||||
logger: logger.With(log.ModuleKey, ServerName),
|
||||
router: chi.NewRouter(),
|
||||
}
|
||||
|
||||
router := chi.NewRouter()
|
||||
s.config = s.Config().(*Config)
|
||||
if len(cfg) > 0 {
|
||||
if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &s.config); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Add CORS middleware around every request
|
||||
// See https://github.com/rs/cors for full option listing
|
||||
router.Use(cors.New(cors.Options{
|
||||
s.router.Use(cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
Debug: false,
|
||||
}).Handler)
|
||||
|
||||
logFile := viper.GetString("log-file")
|
||||
|
||||
port := viper.GetString("gql-port")
|
||||
|
||||
srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: &Resolver{
|
||||
ctx: clientCtx,
|
||||
logFile: logFile,
|
||||
srv := handler.NewDefaultServer(schema.NewExecutableSchema(schema.Config{Resolvers: &Resolver{
|
||||
ctx: clientCtx,
|
||||
// logFile: logFile,
|
||||
}}))
|
||||
|
||||
router.Handle("/", PlaygroundHandler("/api"))
|
||||
s.router.Handle("/", PlaygroundHandler("/api"))
|
||||
|
||||
if viper.GetBool("gql-playground") {
|
||||
apiBase := viper.GetString("gql-playground-api-base")
|
||||
|
||||
router.Handle("/webui", PlaygroundHandler(apiBase+"/api"))
|
||||
router.Handle("/console", PlaygroundHandler(apiBase+"/graphql"))
|
||||
if s.config.Playground {
|
||||
apiBase := s.config.PlaygroundAPIBase
|
||||
s.router.Handle("/webui", PlaygroundHandler(apiBase+"/api"))
|
||||
s.router.Handle("/console", PlaygroundHandler(apiBase+"/graphql"))
|
||||
}
|
||||
|
||||
router.Handle("/api", srv)
|
||||
router.Handle("/graphql", srv)
|
||||
s.router.Handle("/api", srv)
|
||||
s.router.Handle("/graphql", srv)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
errCh := make(chan error)
|
||||
func (s *Server) Name() string {
|
||||
return ServerName
|
||||
}
|
||||
|
||||
go func() {
|
||||
logger.Info(fmt.Sprintf("Connect to GraphQL playground url: http://localhost:%s", port))
|
||||
server := &http.Server{
|
||||
Addr: ":" + port,
|
||||
Handler: router,
|
||||
ReadHeaderTimeout: 3 * time.Second,
|
||||
}
|
||||
errCh <- server.ListenAndServe()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Gracefully stop the GQL server.
|
||||
logger.Info("Stopping GQL server...")
|
||||
// Server configures and starts the GQL server.
|
||||
func (s *Server) Start(ctx context.Context) error {
|
||||
if !s.config.Enable {
|
||||
s.logger.Info(fmt.Sprintf("%s server is disabled via config", s.Name()))
|
||||
return nil
|
||||
case err := <-errCh:
|
||||
logger.Error(fmt.Sprintf("Failed to start GQL server: %s", err))
|
||||
}
|
||||
|
||||
if s.config.Playground {
|
||||
s.logger.Info(fmt.Sprintf("Connect to GraphQL playground URL at http://localhost:%d", s.config.Port))
|
||||
}
|
||||
s.httpServer = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", s.config.Port),
|
||||
Handler: s.router,
|
||||
ReadHeaderTimeout: 3 * time.Second,
|
||||
}
|
||||
if err := s.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
s.logger.Error("Failed to start GraphQL server", "error", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Stop(ctx context.Context) error {
|
||||
if !s.config.Enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.logger.Info("stopping GraphQL server")
|
||||
return s.httpServer.Shutdown(ctx)
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) Config() any {
|
||||
if s.config == nil {
|
||||
return DefaultConfig()
|
||||
}
|
||||
return s.config
|
||||
}
|
||||
|
||||
func (s *Server) StartCmdFlags() *pflag.FlagSet {
|
||||
flags := pflag.NewFlagSet(s.Name(), pflag.ExitOnError)
|
||||
AddGQLFlags(flags)
|
||||
return flags
|
||||
}
|
||||
|
||||
@ -7,13 +7,14 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// NodeDataPath is the path to the laconicd data folder.
|
||||
var NodeDataPath = os.ExpandEnv("$HOME/.laconicd/data")
|
||||
|
||||
func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo, error) {
|
||||
func getStatusInfo(client client.Context) (*schema.NodeInfo, *schema.SyncInfo, *schema.ValidatorInfo, error) {
|
||||
nodeClient, err := client.GetNode()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
@ -23,16 +24,16 @@ func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo,
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return &NodeInfo{
|
||||
return &schema.NodeInfo{
|
||||
ID: string(nodeStatus.NodeInfo.ID()),
|
||||
Network: nodeStatus.NodeInfo.Network,
|
||||
Moniker: nodeStatus.NodeInfo.Moniker,
|
||||
}, &SyncInfo{
|
||||
}, &schema.SyncInfo{
|
||||
LatestBlockHash: nodeStatus.SyncInfo.LatestBlockHash.String(),
|
||||
LatestBlockHeight: strconv.FormatInt(nodeStatus.SyncInfo.LatestBlockHeight, 10),
|
||||
LatestBlockTime: nodeStatus.SyncInfo.LatestBlockTime.String(),
|
||||
CatchingUp: nodeStatus.SyncInfo.CatchingUp,
|
||||
}, &ValidatorInfo{
|
||||
}, &schema.ValidatorInfo{
|
||||
Address: nodeStatus.ValidatorInfo.Address.String(),
|
||||
VotingPower: strconv.FormatInt(nodeStatus.ValidatorInfo.VotingPower, 10),
|
||||
ProposerPriority: nil,
|
||||
@ -40,7 +41,7 @@ func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo,
|
||||
}
|
||||
|
||||
// nolint: all
|
||||
func getNetInfo(_ client.Context) (string, []*PeerInfo, error) {
|
||||
func getNetInfo(_ client.Context) (string, []*schema.PeerInfo, error) {
|
||||
// TODO: Implement
|
||||
|
||||
// nodeClient, err := client.GetNode()
|
||||
@ -68,10 +69,10 @@ func getNetInfo(_ client.Context) (string, []*PeerInfo, error) {
|
||||
|
||||
// return strconv.FormatInt(int64(netInfo.NPeers), 10), peersInfo, nil
|
||||
|
||||
return strconv.FormatInt(int64(0), 10), []*PeerInfo{}, nil
|
||||
return strconv.FormatInt(int64(0), 10), []*schema.PeerInfo{}, nil
|
||||
}
|
||||
|
||||
func getValidatorSet(client client.Context) ([]*ValidatorInfo, error) {
|
||||
func getValidatorSet(client client.Context) ([]*schema.ValidatorInfo, error) {
|
||||
nodeClient, err := client.GetNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -81,10 +82,10 @@ func getValidatorSet(client client.Context) ([]*ValidatorInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
validatorSet := make([]*ValidatorInfo, len(res.Validators))
|
||||
validatorSet := make([]*schema.ValidatorInfo, len(res.Validators))
|
||||
for index, validator := range res.Validators {
|
||||
proposerPriority := strconv.FormatInt(validator.ProposerPriority, 10)
|
||||
validatorSet[index] = &ValidatorInfo{
|
||||
validatorSet[index] = &schema.ValidatorInfo{
|
||||
Address: validator.Address.String(),
|
||||
VotingPower: strconv.FormatInt(validator.VotingPower, 10),
|
||||
ProposerPriority: &proposerPriority,
|
||||
|
||||
73
gql/util.go
73
gql/util.go
@ -9,6 +9,7 @@ import (
|
||||
"github.com/ipld/go-ipld-prime"
|
||||
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
registrytypes "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
@ -23,8 +24,8 @@ const BondIDAttributeName = "bondId"
|
||||
// ExpiryTimeAttributeName denotes the record expiry time.
|
||||
const ExpiryTimeAttributeName = "expiryTime"
|
||||
|
||||
func getGQLCoin(coin sdk.Coin) *Coin {
|
||||
gqlCoin := Coin{
|
||||
func getGQLCoin(coin sdk.Coin) *schema.Coin {
|
||||
gqlCoin := schema.Coin{
|
||||
Type: coin.Denom,
|
||||
Quantity: coin.Amount.BigInt().String(),
|
||||
}
|
||||
@ -32,8 +33,8 @@ func getGQLCoin(coin sdk.Coin) *Coin {
|
||||
return &gqlCoin
|
||||
}
|
||||
|
||||
func getGQLCoins(coins sdk.Coins) []*Coin {
|
||||
gqlCoins := make([]*Coin, len(coins))
|
||||
func getGQLCoins(coins sdk.Coins) []*schema.Coin {
|
||||
gqlCoins := make([]*schema.Coin, len(coins))
|
||||
for index, coin := range coins {
|
||||
gqlCoins[index] = getGQLCoin(coin)
|
||||
}
|
||||
@ -41,12 +42,12 @@ func getGQLCoins(coins sdk.Coins) []*Coin {
|
||||
return gqlCoins
|
||||
}
|
||||
|
||||
func GetGQLNameAuthorityRecord(record *registrytypes.NameAuthority) (*AuthorityRecord, error) {
|
||||
func GetGQLNameAuthorityRecord(record *registrytypes.NameAuthority) (*schema.AuthorityRecord, error) {
|
||||
if record == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &AuthorityRecord{
|
||||
return &schema.AuthorityRecord{
|
||||
OwnerAddress: record.OwnerAddress,
|
||||
OwnerPublicKey: record.OwnerPublicKey,
|
||||
Height: strconv.FormatUint(record.Height, 10),
|
||||
@ -56,7 +57,7 @@ func GetGQLNameAuthorityRecord(record *registrytypes.NameAuthority) (*AuthorityR
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getGQLRecord(ctx context.Context, resolver QueryResolver, record registrytypes.Record) (*Record, error) {
|
||||
func getGQLRecord(ctx context.Context, resolver schema.QueryResolver, record registrytypes.Record) (*schema.Record, error) {
|
||||
// Nil record.
|
||||
if record.Deleted {
|
||||
return nil, nil
|
||||
@ -81,22 +82,22 @@ func getGQLRecord(ctx context.Context, resolver QueryResolver, record registryty
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Record{
|
||||
return &schema.Record{
|
||||
ID: record.Id,
|
||||
BondID: record.GetBondId(),
|
||||
CreateTime: record.GetCreateTime(),
|
||||
ExpiryTime: record.GetExpiryTime(),
|
||||
Owners: record.GetOwners(),
|
||||
Names: record.GetNames(),
|
||||
Attributes: attributes.(MapValue).Value,
|
||||
Attributes: attributes.(schema.MapValue).Value,
|
||||
References: references,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
func resolveIPLDNode(node ipld.Node, links *[]string) (schema.Value, error) {
|
||||
switch node.Kind() {
|
||||
case ipld.Kind_Map:
|
||||
var entries []*Attribute
|
||||
var entries []*schema.Attribute
|
||||
for itr := node.MapIterator(); !itr.Done(); {
|
||||
k, v, err := itr.Next()
|
||||
if err != nil {
|
||||
@ -113,14 +114,14 @@ func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entries = append(entries, &Attribute{
|
||||
entries = append(entries, &schema.Attribute{
|
||||
Key: s,
|
||||
Value: val,
|
||||
})
|
||||
}
|
||||
return MapValue{entries}, nil
|
||||
return schema.MapValue{entries}, nil
|
||||
case ipld.Kind_List:
|
||||
var values []Value
|
||||
var values []schema.Value
|
||||
for itr := node.ListIterator(); !itr.Done(); {
|
||||
_, v, err := itr.Next()
|
||||
if err != nil {
|
||||
@ -132,7 +133,7 @@ func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
}
|
||||
values = append(values, val)
|
||||
}
|
||||
return ArrayValue{values}, nil
|
||||
return schema.ArrayValue{values}, nil
|
||||
case ipld.Kind_Null:
|
||||
return nil, nil
|
||||
case ipld.Kind_Bool:
|
||||
@ -140,82 +141,82 @@ func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return BooleanValue{val}, nil
|
||||
return schema.BooleanValue{val}, nil
|
||||
case ipld.Kind_Int:
|
||||
val, err := node.AsInt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: handle bigger ints
|
||||
return IntValue{int(val)}, nil
|
||||
return schema.IntValue{int(val)}, nil
|
||||
case ipld.Kind_Float:
|
||||
val, err := node.AsFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return FloatValue{val}, nil
|
||||
return schema.FloatValue{val}, nil
|
||||
case ipld.Kind_String:
|
||||
val, err := node.AsString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return StringValue{val}, nil
|
||||
return schema.StringValue{val}, nil
|
||||
case ipld.Kind_Bytes:
|
||||
val, err := node.AsBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return BytesValue{string(val)}, nil
|
||||
return schema.BytesValue{string(val)}, nil
|
||||
case ipld.Kind_Link:
|
||||
val, err := node.AsLink()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*links = append(*links, val.String())
|
||||
return LinkValue{Link(val.String())}, nil
|
||||
return schema.LinkValue{schema.Link(val.String())}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid node kind")
|
||||
}
|
||||
}
|
||||
|
||||
func getGQLNameRecord(record *registrytypes.NameRecord) (*NameRecord, error) {
|
||||
func getGQLNameRecord(record *registrytypes.NameRecord) (*schema.NameRecord, error) {
|
||||
if record == nil {
|
||||
return nil, fmt.Errorf("got nil record")
|
||||
}
|
||||
|
||||
records := make([]*NameRecordEntry, len(record.History))
|
||||
records := make([]*schema.NameRecordEntry, len(record.History))
|
||||
for index, entry := range record.History {
|
||||
records[index] = getNameRecordEntry(entry)
|
||||
}
|
||||
|
||||
return &NameRecord{
|
||||
return &schema.NameRecord{
|
||||
Latest: getNameRecordEntry(record.Latest),
|
||||
History: records,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getNameRecordEntry(record *registrytypes.NameRecordEntry) *NameRecordEntry {
|
||||
return &NameRecordEntry{
|
||||
func getNameRecordEntry(record *registrytypes.NameRecordEntry) *schema.NameRecordEntry {
|
||||
return &schema.NameRecordEntry{
|
||||
ID: record.Id,
|
||||
Height: strconv.FormatUint(record.Height, 10),
|
||||
}
|
||||
}
|
||||
|
||||
func getGQLBond(bondObj *bondtypes.Bond) (*Bond, error) {
|
||||
func getGQLBond(bondObj *bondtypes.Bond) (*schema.Bond, error) {
|
||||
// Nil record.
|
||||
if bondObj == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &Bond{
|
||||
return &schema.Bond{
|
||||
ID: bondObj.Id,
|
||||
Owner: bondObj.Owner,
|
||||
Balance: getGQLCoins(bondObj.Balance),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getAuctionBid(bid *auctiontypes.Bid) *AuctionBid {
|
||||
return &AuctionBid{
|
||||
func getAuctionBid(bid *auctiontypes.Bid) *schema.AuctionBid {
|
||||
return &schema.AuctionBid{
|
||||
BidderAddress: bid.BidderAddress,
|
||||
Status: bid.Status,
|
||||
CommitHash: bid.CommitHash,
|
||||
@ -227,14 +228,14 @@ func getAuctionBid(bid *auctiontypes.Bid) *AuctionBid {
|
||||
}
|
||||
}
|
||||
|
||||
func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Auction, error) {
|
||||
func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*schema.Auction, error) {
|
||||
if auction == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
numProviders := int(auction.NumProviders)
|
||||
|
||||
gqlAuction := Auction{
|
||||
gqlAuction := schema.Auction{
|
||||
ID: auction.Id,
|
||||
Status: auction.Status,
|
||||
OwnerAddress: auction.OwnerAddress,
|
||||
@ -253,7 +254,7 @@ func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Au
|
||||
FundsReleased: auction.FundsReleased,
|
||||
}
|
||||
|
||||
auctionBids := make([]*AuctionBid, len(bids))
|
||||
auctionBids := make([]*schema.AuctionBid, len(bids))
|
||||
for index, entry := range bids {
|
||||
auctionBids[index] = getAuctionBid(entry)
|
||||
}
|
||||
@ -263,7 +264,7 @@ func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Au
|
||||
return &gqlAuction, nil
|
||||
}
|
||||
|
||||
func toRPCValue(value *ValueInput) *registrytypes.QueryRecordsRequest_ValueInput {
|
||||
func toRPCValue(value *schema.ValueInput) *registrytypes.QueryRecordsRequest_ValueInput {
|
||||
var rpcval registrytypes.QueryRecordsRequest_ValueInput
|
||||
|
||||
switch {
|
||||
@ -295,7 +296,7 @@ func toRPCValue(value *ValueInput) *registrytypes.QueryRecordsRequest_ValueInput
|
||||
return &rpcval
|
||||
}
|
||||
|
||||
func toRPCAttributes(attrs []*KeyValueInput) []*registrytypes.QueryRecordsRequest_KeyValueInput {
|
||||
func toRPCAttributes(attrs []*schema.KeyValueInput) []*registrytypes.QueryRecordsRequest_KeyValueInput {
|
||||
kvPairs := []*registrytypes.QueryRecordsRequest_KeyValueInput{}
|
||||
|
||||
for _, value := range attrs {
|
||||
@ -310,7 +311,7 @@ func toRPCAttributes(attrs []*KeyValueInput) []*registrytypes.QueryRecordsReques
|
||||
return kvPairs
|
||||
}
|
||||
|
||||
func getAuthorityRecord(nameAuthority registrytypes.NameAuthority, auctionQueryClient auctiontypes.QueryClient) (*AuthorityRecord, error) {
|
||||
func getAuthorityRecord(nameAuthority registrytypes.NameAuthority, auctionQueryClient auctiontypes.QueryClient) (*schema.AuthorityRecord, error) {
|
||||
gqlNameAuthorityRecord, err := GetGQLNameAuthorityRecord(&nameAuthority)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -4,6 +4,7 @@ deps:
|
||||
- buf.build/cosmos/cosmos-proto
|
||||
- buf.build/cosmos/gogo-proto
|
||||
- buf.build/googleapis/googleapis
|
||||
- buf.build/protocolbuffers/wellknowntypes
|
||||
lint:
|
||||
use:
|
||||
- DEFAULT
|
||||
|
||||
10
proto/cerc/nitro/v1/p2p.proto
Normal file
10
proto/cerc/nitro/v1/p2p.proto
Normal file
@ -0,0 +1,10 @@
|
||||
syntax = "proto3";
|
||||
package cerc.nitro.v1;
|
||||
|
||||
option go_package = "git.vdb.to/cerc-io/laconicd/server/nitro";
|
||||
|
||||
// P2PMessage wraps a json-encoded Nitro protocols.Message
|
||||
// TODO: proper proto message?
|
||||
message P2PMessage {
|
||||
string content = 1;
|
||||
}
|
||||
65
proto/cerc/nitrobank/v1/tx.proto
Normal file
65
proto/cerc/nitrobank/v1/tx.proto
Normal file
@ -0,0 +1,65 @@
|
||||
syntax = "proto3";
|
||||
package cerc.nitrobank.v1;
|
||||
|
||||
import "cosmos/msg/v1/msg.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.proto";
|
||||
// import "cosmos_proto/cosmos.proto";
|
||||
import "cerc/nitrobank/v1/nitrobank.proto";
|
||||
|
||||
option go_package = "git.vdb.to/cerc-io/laconicd/x/nitrobank";
|
||||
|
||||
// 1. user account initiates opening of ledger channel with consensus-controlled module account as
|
||||
// counterparty
|
||||
//
|
||||
// 2. open-channel request is gossiped to validator set
|
||||
//
|
||||
// 3. validators submit partial signatures for pending open-channel request
|
||||
//
|
||||
// 4. block proposer checks pending open-channel requests and creates ledger channels for those with
|
||||
// complete signatures
|
||||
|
||||
// MsgInitAccount initializes a nitro-based account
|
||||
message MsgInitAccount {
|
||||
string nitro_address = 1;
|
||||
}
|
||||
message MsgInitAccountResponse {}
|
||||
|
||||
// MsgOpenChannel opens a ledger channel with the sending account as a participant
|
||||
message MsgOpenChannel {
|
||||
option (cosmos.msg.v1.signer) = "from_address";
|
||||
|
||||
// TODO: this is the nitro address of the sending account
|
||||
// // Nitro address of sending party
|
||||
string from_address = 1;
|
||||
|
||||
// Nitro address of counterparty
|
||||
string to_address = 2;
|
||||
// Simplified outcome just includes the funding amount from payer
|
||||
string amount = 3;
|
||||
// TODO
|
||||
// uint32 challenge_duration = 3;
|
||||
}
|
||||
message MsgOpenChannelResponse {}
|
||||
|
||||
service Msg {
|
||||
option (cosmos.msg.v1.service) = true;
|
||||
|
||||
rpc ProposeChannel(MsgProposeChannel) returns (MsgProposeChannelResponse) {
|
||||
option (google.api.http).post = "/cerc/nitrobank/v1/propose_channel";
|
||||
}
|
||||
}
|
||||
|
||||
message MsgProposeChannel {
|
||||
option (cosmos.msg.v1.signer) = "from_address";
|
||||
|
||||
// Nitro address of sending party (payer)
|
||||
string from_address = 1;
|
||||
// Nitro address of counterparty
|
||||
string to_address = 2;
|
||||
// Simplified outcome just includes the funding amount from payer
|
||||
string amount = 3;
|
||||
// TODO
|
||||
// uint32 challenge_duration = 3;
|
||||
}
|
||||
message MsgProposeChannelResponse {}
|
||||
@ -21,10 +21,8 @@ message Participant {
|
||||
[ (gogoproto.moretags) =
|
||||
"json:\"cosmos_address\" yaml:\"cosmos_address\"" ];
|
||||
|
||||
// participant's Nitro address
|
||||
string nitro_address = 2
|
||||
[ (gogoproto.moretags) =
|
||||
"json:\"nitro_address\" yaml:\"nitro_address\"" ];
|
||||
// full public key used to derive participant's Nitro address
|
||||
bytes public_key = 2;
|
||||
|
||||
// participant's role (participant | validator)
|
||||
string role = 3 [ (gogoproto.moretags) = "json:\"role\" yaml:\"role\"" ];
|
||||
|
||||
@ -96,7 +96,7 @@ message Record {
|
||||
[ (gogoproto.moretags) = "json:\"attributes\" yaml:\"attributes\"" ];
|
||||
repeated string names = 8
|
||||
[ (gogoproto.moretags) = "json:\"names\" yaml:\"names\"" ];
|
||||
string type = 9 [ (gogoproto.moretags) = "json:\"types\" yaml:\"types\"" ];
|
||||
string types = 9 [ (gogoproto.moretags) = "json:\"types\" yaml:\"types\"" ];
|
||||
}
|
||||
|
||||
// AuthorityEntry defines a registry authority
|
||||
|
||||
112
scripts/init.sh
112
scripts/init.sh
@ -1,6 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
KEY="alice"
|
||||
if [[ -n "$CERC_SCRIPT_DEBUG" ]]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
LACONIC_BIN=${LACONIC_BIN:-laconicd}
|
||||
LACONIC_HOME="${LACONIC_HOME:-$HOME/.laconicd}"
|
||||
|
||||
KEY="node_key"
|
||||
CHAINID=${CHAINID:-"laconic_9000-1"}
|
||||
MONIKER=${MONIKER:-"localtestnet"}
|
||||
KEYRING=${KEYRING:-"test"}
|
||||
@ -10,7 +17,22 @@ LOGLEVEL=${LOGLEVEL:-"info"}
|
||||
|
||||
input_genesis_file=${GENESIS_FILE}
|
||||
|
||||
if [ "$1" == "clean" ] || [ ! -d "$HOME/.laconicd/data/blockstore.db" ]; then
|
||||
laconicd="$LACONIC_BIN --home=$LACONIC_HOME --log_level=debug"
|
||||
|
||||
set -e
|
||||
|
||||
hang() {
|
||||
tail -f /dev/null
|
||||
}
|
||||
trap hang EXIT
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed_i="sed -i ''"
|
||||
else
|
||||
sed_i="sed -i"
|
||||
fi
|
||||
|
||||
if [[ "$1" == "clean" ]] || [[ ! -d "$LACONIC_HOME/data/blockstore.db" ]]; then
|
||||
# validate dependencies are installed
|
||||
command -v jq > /dev/null 2>&1 || {
|
||||
echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"
|
||||
@ -18,29 +40,29 @@ if [ "$1" == "clean" ] || [ ! -d "$HOME/.laconicd/data/blockstore.db" ]; then
|
||||
}
|
||||
|
||||
# remove existing daemon and client
|
||||
rm -rf $HOME/.laconicd/*
|
||||
rm -rf $LACONIC_HOME/*
|
||||
|
||||
if [ -n "`which make`" ]; then
|
||||
make install
|
||||
fi
|
||||
|
||||
laconicd config set client chain-id $CHAINID
|
||||
laconicd config set client keyring-backend $KEYRING
|
||||
$laconicd config set client chain-id $CHAINID
|
||||
$laconicd config set client keyring-backend $KEYRING
|
||||
|
||||
# if $KEY exists it should be deleted
|
||||
laconicd keys add $KEY --keyring-backend $KEYRING
|
||||
printf "y\n" | $laconicd keys add $KEY --keyring-backend $KEYRING --no-backup
|
||||
|
||||
# Set the Nitro node PK
|
||||
# TODO generate?
|
||||
echo "$NITRO_PK" | $laconicd keys import-hex "${KEY}_nitro"
|
||||
|
||||
# Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer)
|
||||
laconicd init $MONIKER --chain-id $CHAINID --default-denom $DENOM
|
||||
$laconicd init $MONIKER --chain-id $CHAINID --default-denom $DENOM
|
||||
|
||||
if [[ -f ${input_genesis_file} ]]; then
|
||||
# Use provided genesis config
|
||||
cp $input_genesis_file $HOME/.laconicd/config/genesis.json
|
||||
cp $input_genesis_file $LACONIC_HOME/config/genesis.json
|
||||
fi
|
||||
|
||||
update_genesis() {
|
||||
jq "$1" $HOME/.laconicd/config/genesis.json > $HOME/.laconicd/config/tmp_genesis.json &&
|
||||
mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
||||
jq "$1" $LACONIC_HOME/config/genesis.json > $LACONIC_HOME/config/tmp_genesis.json &&
|
||||
mv $LACONIC_HOME/config/tmp_genesis.json $LACONIC_HOME/config/genesis.json
|
||||
}
|
||||
|
||||
if [[ "$TEST_REGISTRY_EXPIRY" == "true" ]]; then
|
||||
@ -93,49 +115,55 @@ if [ "$1" == "clean" ] || [ ! -d "$HOME/.laconicd/data/blockstore.db" ]; then
|
||||
# Set gas limit in genesis
|
||||
update_genesis '.consensus["params"]["block"]["max_gas"]="10000000"'
|
||||
|
||||
# disable produce empty block
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.laconicd/config/config.toml
|
||||
else
|
||||
sed -i 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.laconicd/config/config.toml
|
||||
fi
|
||||
update_config() {
|
||||
mv -f "$2" "${2}.bak" && tomlq --toml-output "$1" "${2}.bak" > "$2"
|
||||
}
|
||||
|
||||
# Run this to allow requests from any origin
|
||||
sed -i 's/cors_allowed_origins.*$/cors_allowed_origins = ["*"]/' $HOME/.laconicd/config/config.toml
|
||||
# disable empty blocks
|
||||
update_config '.consensus.create_empty_blocks = false' $LACONIC_HOME/config/config.toml
|
||||
|
||||
# Allow requests from any origin
|
||||
update_config '.rpc.cors_allowed_origins = ["*"]' $LACONIC_HOME/config/config.toml
|
||||
|
||||
# Enable telemetry (prometheus metrics: http://localhost:1317/metrics?format=prometheus)
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' 's/enabled = false/enabled = true/g' $HOME/.laconicd/config/app.toml
|
||||
sed -i '' 's/prometheus-retention-time = 0/prometheus-retention-time = 60/g' $HOME/.laconicd/config/app.toml
|
||||
sed -i '' 's/prometheus = false/prometheus = true/g' $HOME/.laconicd/config/config.toml
|
||||
else
|
||||
sed -i 's/enabled = false/enabled = true/g' $HOME/.laconicd/config/app.toml
|
||||
sed -i 's/prometheus-retention-time = 0/prometheus-retention-time = 60/g' $HOME/.laconicd/config/app.toml
|
||||
sed -i 's/prometheus = false/prometheus = true/g' $HOME/.laconicd/config/config.toml
|
||||
fi
|
||||
update_config '.telemetry.enabled = true' $LACONIC_HOME/config/app.toml
|
||||
update_config '.telemetry."prometheus-retention-time" = 60' $LACONIC_HOME/config/app.toml
|
||||
update_config '.instrumentation.prometheus = true' $LACONIC_HOME/config/config.toml
|
||||
|
||||
# Nitro config
|
||||
update_config "
|
||||
.nitro.\"eth-pk\" = \"${KEY}\" |
|
||||
.nitro.\"eth-url\" = \"${NITRO_ETH_URL}\" |
|
||||
.nitro.\"eth-ca-address\" = \"${NITRO_ETH_CA_ADDRESS}\" |
|
||||
.nitro.\"eth-na-address\" = \"${NITRO_ETH_NA_ADDRESS}\" |
|
||||
.nitro.\"eth-vpa-address\" = \"${NITRO_ETH_VPA_ADDRESS}\" |
|
||||
.nitro.\"eth-start-block\" = \"${NITRO_ETH_START_BLOCK}\" |
|
||||
.nitro.pk = \"${KEY}_nitro\" |
|
||||
.nitro.\"boot-peers\" = \"${NITRO_BOOT_PEERS}\"
|
||||
" $LACONIC_HOME/config/app.toml
|
||||
|
||||
# Allocate genesis accounts (cosmos formatted addresses)
|
||||
# 10^30 alnt | 10^12 lnt
|
||||
laconicd genesis add-genesis-account $KEY 1000000000000000000000000000000$DENOM --keyring-backend $KEYRING
|
||||
$laconicd genesis add-genesis-account $KEY 1000000000000000000000000000000$DENOM --keyring-backend $KEYRING
|
||||
|
||||
# Sign genesis transaction
|
||||
# 10^15 alnt
|
||||
laconicd genesis gentx $KEY $STAKING_AMOUNT$DENOM --keyring-backend $KEYRING --chain-id $CHAINID
|
||||
$laconicd genesis gentx $KEY $STAKING_AMOUNT$DENOM --keyring-backend $KEYRING --chain-id $CHAINID
|
||||
|
||||
# Collect genesis tx
|
||||
laconicd genesis collect-gentxs
|
||||
$laconicd genesis collect-gentxs
|
||||
|
||||
# Run this to ensure everything worked and that the genesis file is setup correctly
|
||||
laconicd genesis validate
|
||||
$laconicd genesis validate
|
||||
else
|
||||
echo "Using existing database at $HOME/.laconicd. To replace, run '`basename $0` clean'"
|
||||
echo "Using existing database at $LACONIC_HOME. To replace, run '`basename $0` clean'"
|
||||
fi
|
||||
|
||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
||||
laconicd start \
|
||||
--pruning=nothing \
|
||||
--log_level $LOGLEVEL \
|
||||
--minimum-gas-prices=1$DENOM \
|
||||
--api.enable \
|
||||
# TODO new pruning config
|
||||
$laconicd start \
|
||||
--log_level "$LOGLEVEL" \
|
||||
--server.minimum-gas-prices="1$DENOM" \
|
||||
--rpc.laddr="tcp://0.0.0.0:26657" \
|
||||
--gql-server --gql-playground
|
||||
--grpc.address="127.0.0.1:9091" \
|
||||
--gql.enable --gql.playground
|
||||
|
||||
13
server/distsig/config.go
Normal file
13
server/distsig/config.go
Normal file
@ -0,0 +1,13 @@
|
||||
package distsig
|
||||
|
||||
type Config struct {
|
||||
LongtermKey string `mapstructure:"longterm-key" toml:"longterm-key" comment:"The long-term key used in distributed signatures"`
|
||||
// TODO: set this in genesis
|
||||
ThresholdRatio float64 `mapstructure:"threshold-ratio" toml:"threshold-ratio" comment:"The ratio of signers required to sign a message"`
|
||||
}
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
ThresholdRatio: 4. / 7,
|
||||
}
|
||||
}
|
||||
175
server/distsig/distsig_test.go
Normal file
175
server/distsig/distsig_test.go
Normal file
@ -0,0 +1,175 @@
|
||||
package distsig
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"git.vdb.to/cerc-io/chainsig/ethschnorr"
|
||||
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/testutil"
|
||||
)
|
||||
|
||||
func NewTestManager(t *testing.T) (*Manager, Point) {
|
||||
logger := log.NewTestLogger(t)
|
||||
kr := testutil.NewKeyring()
|
||||
accounts := sdktestutil.CreateKeyringAccounts(t, kr, 1)
|
||||
cfg := DefaultConfig()
|
||||
cfg.LongtermKey = accounts[0].Name
|
||||
|
||||
dsm, err := New(logger, cfg, kr)
|
||||
require.NoError(t, err)
|
||||
|
||||
longterm, err := kr.Key(cfg.LongtermKey)
|
||||
require.NoError(t, err)
|
||||
longtermPoint, err := KeyRecordToPoint(longterm)
|
||||
require.NoError(t, err)
|
||||
|
||||
return dsm, longtermPoint
|
||||
}
|
||||
|
||||
type round struct {
|
||||
name string
|
||||
verify func(*Manager) error
|
||||
tweak func([]PeerMessages)
|
||||
}
|
||||
|
||||
var (
|
||||
dkgRounds = []round{
|
||||
{
|
||||
name: "deal",
|
||||
},
|
||||
{
|
||||
name: "response",
|
||||
verify: func(m *Manager) error {
|
||||
if !m.currentDkg().Certified() {
|
||||
return errors.New("not certified")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "commit",
|
||||
verify: func(m *Manager) error {
|
||||
if !m.currentDkg().Finished() {
|
||||
return errors.New("run not finished")
|
||||
}
|
||||
if m.currentDkg().share == nil {
|
||||
return errors.New("dist key share is absent")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
dssRounds = []round{
|
||||
{
|
||||
name: "sign",
|
||||
verify: func(m *Manager) error {
|
||||
dss := m.sigs[m.completeSigs[0]]
|
||||
if dss.sig == nil {
|
||||
return errors.New("signature is nil")
|
||||
}
|
||||
dkg, err := m.getDkg(dss.dkgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ethschnorr.Verify(dkg.share.Public(), dss.Message(), dss.sig)
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func runRound(t *testing.T, r round, members []*Manager) {
|
||||
buf := make([]PeerMessages, len(members))
|
||||
for i := range members {
|
||||
buf[i] = members[i].FlushMessages()
|
||||
}
|
||||
if r.tweak != nil {
|
||||
r.tweak(buf)
|
||||
}
|
||||
for i := range members {
|
||||
for j := range members {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
require.NoError(t, members[i].ProcessMessages(&buf[j]),
|
||||
"round=%s, i=%d, j=%d", r.name, i, j)
|
||||
}
|
||||
}
|
||||
if r.verify != nil {
|
||||
for i, m := range members {
|
||||
require.NoError(t, r.verify(m), "round=%s, i=%d", r.name, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDkgBasic(t *testing.T) {
|
||||
numMembers := 2
|
||||
blockHeight := int64(1)
|
||||
|
||||
members := make([]*Manager, numMembers)
|
||||
pubkeys := make([]Point, numMembers)
|
||||
for i := range members {
|
||||
members[i], pubkeys[i] = NewTestManager(t)
|
||||
}
|
||||
t.Logf("DKG with %d members", numMembers)
|
||||
|
||||
for i, m := range members {
|
||||
require.NoError(t, m.StartDKG(blockHeight, pubkeys), "i=%d", i)
|
||||
}
|
||||
for _, r := range dkgRounds {
|
||||
runRound(t, r, members)
|
||||
}
|
||||
|
||||
require.False(t, members[0].NeedDKG(pubkeys))
|
||||
require.Error(t, members[0].StartDKG(blockHeight, pubkeys))
|
||||
|
||||
// add participants and refresh DKG
|
||||
for len(members) < 7 {
|
||||
blockHeight++
|
||||
|
||||
m, pub := NewTestManager(t)
|
||||
members = append(members, m)
|
||||
pubkeys = append(pubkeys, pub)
|
||||
t.Logf("DKG with %d members", len(members))
|
||||
|
||||
for i, m := range members {
|
||||
require.True(t, m.NeedDKG(pubkeys), "i=%d", i)
|
||||
require.NoError(t, m.StartDKG(blockHeight, pubkeys), "i=%d", i)
|
||||
}
|
||||
for _, r := range dkgRounds {
|
||||
runRound(t, r, members)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignatureBasic(t *testing.T) {
|
||||
numMembers := 7
|
||||
|
||||
members := make([]*Manager, numMembers)
|
||||
pubkeys := make([]Point, numMembers)
|
||||
for i := range members {
|
||||
members[i], pubkeys[i] = NewTestManager(t)
|
||||
}
|
||||
|
||||
for _, m := range members {
|
||||
require.NoError(t, m.StartDKG(1, pubkeys))
|
||||
}
|
||||
for _, r := range dkgRounds {
|
||||
runRound(t, r, members)
|
||||
}
|
||||
|
||||
msg := big.NewInt(42)
|
||||
for _, m := range members {
|
||||
require.NoError(t, m.StartSignature(m.currentDkgID, msg))
|
||||
}
|
||||
runRound(t, dssRounds[0], members)
|
||||
|
||||
require.Error(t, members[0].StartSignature(0, msg))
|
||||
|
||||
require.NoError(t, members[0].StartDKG(2, pubkeys[:3]))
|
||||
require.Error(t, members[0].StartSignature(2, msg))
|
||||
}
|
||||
19
server/distsig/flags.go
Normal file
19
server/distsig/flags.go
Normal file
@ -0,0 +1,19 @@
|
||||
package distsig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func prefix(f string) string {
|
||||
return fmt.Sprintf("%s.%s", componentName, f)
|
||||
}
|
||||
|
||||
var (
|
||||
FlagLongtermKey = prefix("longterm-key")
|
||||
)
|
||||
|
||||
func AddNitroFlags(flags *pflag.FlagSet) {
|
||||
flags.String(FlagLongtermKey, "", "The long-term key used in distributed signatures")
|
||||
}
|
||||
224
server/distsig/keygen.go
Normal file
224
server/distsig/keygen.go
Normal file
@ -0,0 +1,224 @@
|
||||
package distsig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
dkg "go.dedis.ch/kyber/v3/share/dkg/rabin"
|
||||
)
|
||||
|
||||
// DkgMessages collects local DKG messages that are pending broadcast.
|
||||
type DkgMessages struct {
|
||||
runID DkgRunID
|
||||
messages []dkgMessage
|
||||
}
|
||||
|
||||
// DKG steps (actions) that are executed by the DKG protocol
|
||||
type dkgStep int
|
||||
|
||||
const (
|
||||
dkg_deal dkgStep = iota
|
||||
dkg_certify
|
||||
dkg_commit
|
||||
dkg_finish
|
||||
dkg_done
|
||||
)
|
||||
|
||||
type dkgRun struct {
|
||||
*dkg.DistKeyGenerator
|
||||
// runID RunID
|
||||
msgBuffer []dkgMessage
|
||||
step dkgStep
|
||||
share *dkg.DistKeyShare
|
||||
}
|
||||
|
||||
type dkgMessage interface {
|
||||
send(*dkgRun) (dkgMessage, error)
|
||||
from() uint32
|
||||
target() uint32
|
||||
}
|
||||
|
||||
// prepareMessages produces DKG state transitions that don't rely on peer inputs, i.e. the deal or
|
||||
// commit steps. This is called during ExtendVote by all validators.
|
||||
func (d *dkgRun) prepareMessages() error {
|
||||
out, err := d.handleMessage(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if out != nil {
|
||||
d.msgBuffer = append(d.msgBuffer, out...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dkgRun) flushMessages() []dkgMessage {
|
||||
buf := d.msgBuffer
|
||||
d.msgBuffer = nil
|
||||
return buf
|
||||
}
|
||||
|
||||
// processMessages processes incoming DKG messages and produces outgoing messages. This is called
|
||||
// during VerifyVoteExtension by all validators (TODO: verify).
|
||||
func (d *dkgRun) processMessages(in []dkgMessage) error {
|
||||
for _, msg := range in {
|
||||
out, err := d.handleMessage(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if out != nil {
|
||||
d.msgBuffer = append(d.msgBuffer, out...)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dkgRun) handleMessage(in dkgMessage) ([]dkgMessage, error) {
|
||||
// fmt.Printf("[%d, %7s] handle: %T", d.index, d.step, in)
|
||||
// if in != nil {
|
||||
// fmt.Printf(" (from %d to %+v)", in.from(), in.target())
|
||||
// }
|
||||
// fmt.Println()
|
||||
|
||||
// nil input means we try to execute a step requiring no peer input
|
||||
if in == nil {
|
||||
var out []dkgMessage
|
||||
switch d.step {
|
||||
case dkg_deal:
|
||||
deals, err := d.Deals()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for index, deal := range deals {
|
||||
out = append(out, msgDeal{index: uint32(index), msg: deal})
|
||||
}
|
||||
case dkg_commit:
|
||||
sc, err := d.SecretCommits()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = []dkgMessage{msgSecretCommits{msg: sc}}
|
||||
case dkg_done:
|
||||
dks, err := d.DistKeyShare()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.share = dks
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected stage: %v", d.step)
|
||||
}
|
||||
d.step = nextStep(d.step)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
var out []dkgMessage
|
||||
if msg, err := in.send(d); err != nil {
|
||||
return nil, err
|
||||
} else if msg != nil {
|
||||
out = []dkgMessage{msg}
|
||||
}
|
||||
if (d.step == dkg_certify && d.Certified()) ||
|
||||
(d.step == dkg_finish && d.Finished()) {
|
||||
d.step = nextStep(d.step)
|
||||
msgs, err := d.handleMessage(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, msgs...)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func nextStep(step dkgStep) dkgStep {
|
||||
if step == dkg_done {
|
||||
return dkg_done
|
||||
}
|
||||
return step + 1
|
||||
}
|
||||
|
||||
type (
|
||||
msgDeal struct {
|
||||
msg *dkg.Deal
|
||||
index uint32 // recipient index
|
||||
}
|
||||
msgResponse struct{ msg *dkg.Response }
|
||||
msgJustification struct{ msg *dkg.Justification }
|
||||
msgSecretCommits struct{ msg *dkg.SecretCommits }
|
||||
msgComplaintCommits struct{ msg *dkg.ComplaintCommits }
|
||||
msgReconstructCommits struct{ msg *dkg.ReconstructCommits }
|
||||
)
|
||||
|
||||
func (m msgDeal) send(d *dkgRun) (dkgMessage, error) {
|
||||
if m.index != uint32(d.Index()) {
|
||||
return nil, nil
|
||||
}
|
||||
out, err := d.ProcessDeal(m.msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return msgResponse{out}, nil
|
||||
}
|
||||
|
||||
func (m msgResponse) send(d *dkgRun) (dkgMessage, error) {
|
||||
if out, err := d.ProcessResponse(m.msg); err != nil {
|
||||
return nil, err
|
||||
} else if out != nil {
|
||||
return msgJustification{out}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m msgJustification) send(d *dkgRun) (dkgMessage, error) {
|
||||
return nil, d.ProcessJustification(m.msg)
|
||||
}
|
||||
|
||||
func (m msgSecretCommits) send(d *dkgRun) (dkgMessage, error) {
|
||||
if out, err := d.ProcessSecretCommits(m.msg); err != nil {
|
||||
return nil, err
|
||||
} else if out != nil {
|
||||
return msgComplaintCommits{out}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m msgComplaintCommits) send(d *dkgRun) (dkgMessage, error) {
|
||||
out, err := d.ProcessComplaintCommits(m.msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return msgReconstructCommits{out}, nil
|
||||
}
|
||||
|
||||
func (m msgReconstructCommits) send(d *dkgRun) (dkgMessage, error) {
|
||||
return nil, d.ProcessReconstructCommits(m.msg)
|
||||
}
|
||||
|
||||
func (d dkgStep) String() string {
|
||||
switch d {
|
||||
case dkg_deal:
|
||||
return "deal"
|
||||
case dkg_certify:
|
||||
return "certify"
|
||||
case dkg_commit:
|
||||
return "commit"
|
||||
case dkg_finish:
|
||||
return "finish"
|
||||
case dkg_done:
|
||||
return "done"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// for debugging
|
||||
func (m msgDeal) from() uint32 { return m.msg.Index }
|
||||
func (m msgResponse) from() uint32 { return m.msg.Response.Index }
|
||||
func (m msgJustification) from() uint32 { return m.msg.Justification.Index }
|
||||
func (m msgSecretCommits) from() uint32 { return m.msg.Index }
|
||||
func (m msgComplaintCommits) from() uint32 { return m.msg.Index }
|
||||
func (m msgReconstructCommits) from() uint32 { return m.msg.Index }
|
||||
|
||||
func (m msgDeal) target() uint32 { return m.index }
|
||||
func (m msgResponse) target() uint32 { return m.msg.Index }
|
||||
func (m msgJustification) target() uint32 { return m.msg.Index }
|
||||
func (m msgSecretCommits) target() uint32 { return 0 }
|
||||
func (m msgComplaintCommits) target() uint32 { return m.msg.DealerIndex }
|
||||
func (m msgReconstructCommits) target() uint32 { return m.msg.DealerIndex }
|
||||
280
server/distsig/manager.go
Normal file
280
server/distsig/manager.go
Normal file
@ -0,0 +1,280 @@
|
||||
package distsig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
dkg "go.dedis.ch/kyber/v3/share/dkg/rabin"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
|
||||
clientdss "git.vdb.to/cerc-io/chainsig/ethdss"
|
||||
"git.vdb.to/cerc-io/chainsig/ethschnorr"
|
||||
"git.vdb.to/cerc-io/laconicd/utils"
|
||||
)
|
||||
|
||||
type (
|
||||
DealMap = map[int]*dkg.Deal
|
||||
|
||||
DkgRunID int64
|
||||
SigRunID string
|
||||
)
|
||||
|
||||
const (
|
||||
componentName = "distsig"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
config *Config
|
||||
logger log.Logger
|
||||
longterm Scalar
|
||||
longtermPubKey cryptotypes.PubKey
|
||||
|
||||
dkgs map[DkgRunID]*dkgRun
|
||||
currentDkgID DkgRunID // zero indicates no current run
|
||||
|
||||
sigs map[SigRunID]*sigRun
|
||||
completeSigs []SigRunID
|
||||
}
|
||||
|
||||
type PeerMessages struct {
|
||||
dkg *DkgMessages
|
||||
dss []SigMessages
|
||||
}
|
||||
|
||||
func New(logger log.Logger, cfg *Config, kr keyring.Keyring) (*Manager, error) {
|
||||
longtermPrivKey, err := utils.ExtractPrivateKey(kr, cfg.LongtermKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract longterm key: %w", err)
|
||||
}
|
||||
m := &Manager{
|
||||
longterm: suite.Scalar().SetBytes(longtermPrivKey.Bytes()),
|
||||
longtermPubKey: longtermPrivKey.PubKey(),
|
||||
config: cfg,
|
||||
dkgs: make(map[DkgRunID]*dkgRun),
|
||||
sigs: make(map[SigRunID]*sigRun),
|
||||
}
|
||||
m.logger = logger.With(log.ModuleKey, m.Name())
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Manager) getDkg(runid DkgRunID) (*dkgRun, error) {
|
||||
if runid == 0 {
|
||||
// runid = m.currentDkg
|
||||
return nil, fmt.Errorf("invalid run ID")
|
||||
}
|
||||
if run, ok := m.dkgs[runid]; ok {
|
||||
return run, nil
|
||||
}
|
||||
return nil, fmt.Errorf("DKG not initialized for run: %v", runid)
|
||||
}
|
||||
|
||||
func (m *Manager) currentDkg() *dkgRun {
|
||||
run, err := m.getDkg(m.currentDkgID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return run
|
||||
}
|
||||
|
||||
func (m *Manager) LongtermPublicKey() cryptotypes.PubKey {
|
||||
return m.longtermPubKey
|
||||
}
|
||||
|
||||
func (m *Manager) LongtermEthAddress() common.Address {
|
||||
pubkey, err := SuitePublicKeyFromBytes(m.LongtermPublicKey().Bytes())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to parse longterm pubkey: %w", err))
|
||||
}
|
||||
return pubkey.Address()
|
||||
}
|
||||
|
||||
func thresholdForRatio(m int, tr float64) int {
|
||||
return int(math.Ceil(float64(m) * tr))
|
||||
}
|
||||
|
||||
func (m *Manager) initDKG(members []Point) (*dkgRun, error) {
|
||||
t := thresholdForRatio(len(members), m.config.ThresholdRatio)
|
||||
keygen, err := dkg.NewDistKeyGenerator(suite.(dkg.Suite), m.longterm, members, t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dkgRun{DistKeyGenerator: keygen}, nil
|
||||
}
|
||||
|
||||
// NeedDKG returns true if DKG needs to be run for the given participants.
|
||||
func (m *Manager) NeedDKG(pubkeys []Point) bool {
|
||||
return m.currentDkgID == 0 || !equalPoints(m.currentDkg().Participants(), pubkeys)
|
||||
}
|
||||
|
||||
// StartDKG begins a new DKG run including the given participants.
|
||||
func (m *Manager) StartDKG(block int64, pubkeys []Point) error {
|
||||
// TODO: generate runid from block height and hash of pubkeys?
|
||||
runid := DkgRunID(block)
|
||||
if _, ok := m.dkgs[runid]; ok {
|
||||
return fmt.Errorf("DKG run %v already exists", runid)
|
||||
}
|
||||
if len(pubkeys) < 2 {
|
||||
m.currentDkgID = 0
|
||||
m.logger.Debug("Too few participants for distributed signature")
|
||||
return nil
|
||||
}
|
||||
run, err := m.initDKG(pubkeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.dkgs[runid] = run
|
||||
m.currentDkgID = runid
|
||||
return run.prepareMessages()
|
||||
}
|
||||
|
||||
func (m *Manager) initDSS(dkgid DkgRunID, msg *big.Int) (*sigRun, error) {
|
||||
run, err := m.getDkg(dkgid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !run.Finished() {
|
||||
return nil, fmt.Errorf("DKG run has not finished: %v", dkgid)
|
||||
}
|
||||
random, err := run.DistKeyShare()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dss, err := clientdss.NewDSS(clientdss.DSSArgs{
|
||||
Secret: m.longterm,
|
||||
Participants: run.Participants(),
|
||||
Long: run.share,
|
||||
Random: random,
|
||||
Msg: msg,
|
||||
T: run.Threshold(),
|
||||
// Qualified: run.QUAL(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sigRun{DSS: dss, dkgID: dkgid}, nil
|
||||
}
|
||||
|
||||
// StartSignature begins a DSS run for the given message and DKG state.
|
||||
func (m *Manager) StartSignature(msg *big.Int) error {
|
||||
if m.currentDkgID == 0 {
|
||||
return fmt.Errorf("no distributed key prepared")
|
||||
}
|
||||
run, err := m.initDSS(m.currentDkgID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sigid := run.SigRunID()
|
||||
m.sigs[sigid] = run
|
||||
return run.prepareMessages()
|
||||
}
|
||||
|
||||
func (m *Manager) CompletedSignatures() map[SigRunID]ethschnorr.Signature {
|
||||
var ret map[SigRunID]ethschnorr.Signature
|
||||
for _, id := range m.completeSigs {
|
||||
run, ok := m.sigs[id]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("DSS run not found: %v", id))
|
||||
}
|
||||
if run.sig == nil {
|
||||
panic(fmt.Errorf("DSS signature not completed: %v", id))
|
||||
}
|
||||
// Deterministically pick a participant responsible for submitting the signature
|
||||
session := new(big.Int).SetBytes(run.SessionID()[:8])
|
||||
submitterIdx := session.Uint64() % uint64(len(run.Participants()))
|
||||
if run.Index() == int(submitterIdx) {
|
||||
ret[id] = run.sig
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// FlushMessages flushes the message buffers for any active DKG and DSS runs.
|
||||
func (m *Manager) FlushMessages() PeerMessages {
|
||||
var ret PeerMessages
|
||||
if buf := m.currentDkg().flushMessages(); len(buf) != 0 {
|
||||
ret.dkg = &DkgMessages{runID: m.currentDkgID, messages: buf}
|
||||
}
|
||||
for id, run := range m.sigs {
|
||||
if buf := run.flushMessages(); buf != nil {
|
||||
ret.dss = append(ret.dss, SigMessages{id, buf})
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ProcessMessages processes DKG and DSS peer messages.
|
||||
func (m *Manager) ProcessMessages(dm *PeerMessages) error {
|
||||
if dkg := dm.dkg; dkg != nil {
|
||||
run, err := m.getDkg(dkg.runID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := run.processMessages(dkg.messages); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, dss := range dm.dss {
|
||||
run, ok := m.sigs[dss.runID]
|
||||
if !ok {
|
||||
return fmt.Errorf("DSS not initialized for run: %v", dss.runID)
|
||||
}
|
||||
if err := run.processMessage(dss.messages); err != nil {
|
||||
return err
|
||||
}
|
||||
if run.sig != nil {
|
||||
m.completeSigs = append(m.completeSigs, dss.runID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func equalPoints(a, b []Point) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, p := range a {
|
||||
if !p.Equal(b[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*Manager) Name() string { return componentName }
|
||||
func (*Manager) Start(context.Context) error { return nil }
|
||||
func (*Manager) Stop(context.Context) error { return nil }
|
||||
|
||||
func (m *Manager) Config() any {
|
||||
if m.config == nil {
|
||||
return DefaultConfig()
|
||||
}
|
||||
return m.config
|
||||
}
|
||||
|
||||
func (pm PeerMessages) Empty() bool {
|
||||
return pm.dkg == nil && len(pm.dss) == 0
|
||||
}
|
||||
|
||||
func UnmarshalConfig(cfg map[string]any) (*Config, error) {
|
||||
config := DefaultConfig()
|
||||
if err := serverv2.UnmarshalSubConfig(cfg, componentName, config); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %T: %w", config, err)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func ProvideManager(logger log.Logger, globalConfig runtime.GlobalConfig, kr keyring.Keyring) (*Manager, error) {
|
||||
config, err := UnmarshalConfig(globalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return New(logger, config, kr)
|
||||
}
|
||||
61
server/distsig/signature.go
Normal file
61
server/distsig/signature.go
Normal file
@ -0,0 +1,61 @@
|
||||
package distsig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
clientdss "git.vdb.to/cerc-io/chainsig/ethdss"
|
||||
"git.vdb.to/cerc-io/chainsig/ethschnorr"
|
||||
)
|
||||
|
||||
type SigMessages struct {
|
||||
runID SigRunID
|
||||
messages sigMessage
|
||||
}
|
||||
|
||||
type sigStep int
|
||||
|
||||
const (
|
||||
sig_partial sigStep = iota
|
||||
sig_complete
|
||||
)
|
||||
|
||||
type sigRun struct {
|
||||
*clientdss.DSS
|
||||
msgBuffer sigMessage
|
||||
|
||||
dkgID DkgRunID
|
||||
step sigStep
|
||||
|
||||
sig ethschnorr.Signature
|
||||
}
|
||||
|
||||
type sigMessage = *clientdss.PartialSig
|
||||
|
||||
func (d *sigRun) SigRunID() SigRunID {
|
||||
return SigRunID(fmt.Sprintf("%020d-%x", d.dkgID, d.SessionID()[:10]))
|
||||
}
|
||||
|
||||
func (d *sigRun) prepareMessages() error {
|
||||
var err error
|
||||
d.msgBuffer, err = d.PartialSig()
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *sigRun) flushMessages() sigMessage {
|
||||
buf := d.msgBuffer
|
||||
d.msgBuffer = nil
|
||||
return buf
|
||||
}
|
||||
|
||||
func (d *sigRun) processMessage(in sigMessage) error {
|
||||
err := d.ProcessPartialSig(in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// return d.EnoughPartialSig(), nil
|
||||
if d.EnoughPartialSig() {
|
||||
d.sig, err = d.Signature()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
37
server/distsig/suite.go
Normal file
37
server/distsig/suite.go
Normal file
@ -0,0 +1,37 @@
|
||||
package distsig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.vdb.to/cerc-io/chainsig/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"go.dedis.ch/kyber/v3"
|
||||
"go.dedis.ch/kyber/v3/suites"
|
||||
)
|
||||
|
||||
type (
|
||||
Scalar = kyber.Scalar
|
||||
Point = kyber.Point
|
||||
|
||||
PublicKey = secp256k1.PublicKey
|
||||
)
|
||||
|
||||
var (
|
||||
suite suites.Suite = secp256k1.NewBlakeKeccackSecp256k1()
|
||||
|
||||
// Note: the compressed encoding of pubkeys used by the SDK and our library are the same.
|
||||
// See gitlab.com/yawning/secp256k1-voi/secec
|
||||
SuitePublicKeyFromBytes = secp256k1.NewPublicKeyFromBytes
|
||||
)
|
||||
|
||||
func KeyRecordToPoint(longterm *keyring.Record) (kyber.Point, error) {
|
||||
pubkey, err := longterm.GetPubKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to access public key: %w", err)
|
||||
}
|
||||
suitePubkey, err := SuitePublicKeyFromBytes(pubkey.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode public key: %w", err)
|
||||
}
|
||||
return suitePubkey.Point()
|
||||
}
|
||||
26
server/distsig/utils.go
Normal file
26
server/distsig/utils.go
Normal file
@ -0,0 +1,26 @@
|
||||
package distsig
|
||||
|
||||
import "encoding/hex"
|
||||
|
||||
type BlockHash [32]byte
|
||||
|
||||
func (bh BlockHash) String() string {
|
||||
return hex.EncodeToString(bh[:])
|
||||
}
|
||||
|
||||
func (bh BlockHash) Bytes() []byte {
|
||||
return bh[:]
|
||||
}
|
||||
|
||||
func (bh BlockHash) Equal(other BlockHash) bool {
|
||||
return bh == other
|
||||
}
|
||||
|
||||
func BlockHashFromBytes(b []byte) BlockHash {
|
||||
if len(b) != 32 {
|
||||
panic("invalid block hash length")
|
||||
}
|
||||
var bh BlockHash
|
||||
copy(bh[:], b)
|
||||
return bh
|
||||
}
|
||||
70
server/nitro/commands.go
Normal file
70
server/nitro/commands.go
Normal file
@ -0,0 +1,70 @@
|
||||
package nitro
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/statechannels/go-nitro/channel/state/outcome"
|
||||
gonitrotypes "github.com/statechannels/go-nitro/types"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagAssetAddress = "asset"
|
||||
)
|
||||
|
||||
func (s *Server) OpenChannelCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "open-channel <amount>", // TODO: doc args?
|
||||
Short: "Open a payment channel with the Laconic custodian",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// clientCtx, err := client.GetClientTxContext(cmd)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// TODO
|
||||
// use Coin types for eth and tokens?
|
||||
// how do we map denoms to token addresses?
|
||||
amount, ok := new(big.Int).SetString(args[1], 10)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid amount: %s", args[1])
|
||||
}
|
||||
assetStr, err := cmd.Flags().GetString(FlagAssetAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var asset common.Address // 0 address mean ETH
|
||||
if assetStr != "" {
|
||||
asset = common.HexToAddress(assetStr)
|
||||
}
|
||||
|
||||
destination := LaconicCustodianAddress
|
||||
exit := outcome.Exit{
|
||||
outcome.SingleAssetExit{
|
||||
Asset: asset,
|
||||
Allocations: []outcome.Allocation{
|
||||
{ // TODO: what should initial allocation be?
|
||||
Destination: gonitrotypes.AddressToDestination(s.ethAddress),
|
||||
Amount: amount,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
r, err := s.CreateLedgerChannel(destination, 0, exit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Println("objective response:", r)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
cmd.Flags().String(FlagAssetAddress, "", "The address of the asset to fund the channel with")
|
||||
addClientFlags(cmd.Flags())
|
||||
|
||||
return cmd
|
||||
}
|
||||
35
server/nitro/config.go
Normal file
35
server/nitro/config.go
Normal file
@ -0,0 +1,35 @@
|
||||
package nitro
|
||||
|
||||
type Config struct {
|
||||
// TODO: use keyring
|
||||
Pk string `mapstructure:"pk" toml:"pk" comment:"The private key used by the Nitro node."`
|
||||
|
||||
EthPk string `mapstructure:"eth-pk" toml:"eth-pk" comment:"The private key used when interacting with the Ethereum chain."`
|
||||
EthUrl string `mapstructure:"eth-url" toml:"eth-url" comment:"The URL of the Ethereum node to connect to."`
|
||||
EthAuthToken string `mapstructure:"eth-auth-token" toml:"eth-auth-token" comment:"The bearer token used for auth in requests to the Ethereum chain's RPC endpoint."`
|
||||
EthStartBlock uint64 `mapstructure:"eth-start-block" toml:"eth-start-block" comment:"Ethereum block number to start listening for Nitro Adjudicator events."`
|
||||
EthNaAddress string `mapstructure:"eth-na-address" toml:"na-address" comment:"Ethereum address of the Nitro Adjudicator contract."`
|
||||
EthVpaAddress string `mapstructure:"eth-vpa-address" toml:"vpa-address" comment:"Ethereum address of the Virtual Payment App contract."`
|
||||
EthCaAddress string `mapstructure:"eth-ca-address" toml:"ca-address" comment:"Ethereum address of the Consensus App contract."`
|
||||
|
||||
BootPeers string `mapstructure:"boot-peers" toml:"boot-peers" comment:"Comma-delimited list of peer multiaddrs the messaging service will connect to when initialized."`
|
||||
PublicIp string `mapstructure:"public-ip" toml:"public-ip" comment:"The public IP address used for the Nitro message service."`
|
||||
ExtMultiAddr string `mapstructure:"ext-multiaddr" toml:"ext-multiaddr" comment:"An additional external multiaddr to advertise."`
|
||||
MsgPort int `mapstructure:"msg-port" toml:"msg-port" comment:"The TCP port for the Nitro message service."`
|
||||
WsMsgPort int `mapstructure:"ws-msg-port" toml:"ws-msg-port" comment:"The WebSocket port for the Nitro message service."`
|
||||
RpcPort int `mapstructure:"rpc-port" toml:"rpc-port" comment:"The TCP port for the Nitro RPC server."`
|
||||
TlsCertFilepath string `mapstructure:"tls-cert-filepath" toml:"tls-cert-filepath" comment:"Filepath to the TLS certificate. If not specified, TLS will not be used with the RPC transport."`
|
||||
TlsKeyFilepath string `mapstructure:"tls-key-filepath" toml:"tls-key-filepath" comment:"Filepath to the TLS private key. If not specified, TLS will not be used with the RPC transport."`
|
||||
}
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
EthUrl: "http://localhost:8545",
|
||||
PublicIp: "127.0.0.1",
|
||||
MsgPort: 3005,
|
||||
WsMsgPort: 6005,
|
||||
RpcPort: 4005,
|
||||
// TlsCertFilepath: "./tls/statechannels.org.pem",
|
||||
// TlsKeyFilepath: "./tls/statechannels.org_key.pem",
|
||||
}
|
||||
}
|
||||
23
server/nitro/dev_account.go
Normal file
23
server/nitro/dev_account.go
Normal file
@ -0,0 +1,23 @@
|
||||
package nitro
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
)
|
||||
|
||||
var (
|
||||
// (DEV) EOA placeholder for consensus-controlled smart contract account
|
||||
LaconicCustodianAddress common.Address
|
||||
LaconicCustodianPrivKey = secp256k1.PrivKey{Key: crypto.Keccak256([]byte("laconic-custodian"))}
|
||||
// LaconicCustodianPrivKey *ecdsa.PrivateKey
|
||||
)
|
||||
|
||||
func init() {
|
||||
ecdsaPrivKey, err := crypto.ToECDSA(LaconicCustodianPrivKey.Key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
LaconicCustodianAddress = crypto.PubkeyToAddress(ecdsaPrivKey.PublicKey)
|
||||
}
|
||||
103
server/nitro/flags.go
Normal file
103
server/nitro/flags.go
Normal file
@ -0,0 +1,103 @@
|
||||
package nitro
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// start flags are prefixed with the server name
|
||||
func prefix(f string) string {
|
||||
return fmt.Sprintf("%s.%s", serverName, f)
|
||||
}
|
||||
|
||||
var (
|
||||
flag_pk = prefix("pk") // "pk"
|
||||
|
||||
flag_eth_pk = prefix("eth-pk") // "chainpk"
|
||||
flag_eth_url = prefix("eth-url") // "chainurl"
|
||||
flag_eth_start_block = prefix("eth-start-block") // "chainstartblock"
|
||||
flag_eth_auth_token = prefix("eth-auth-token") // "chainauthtoken"
|
||||
flag_eth_na_address = prefix("eth-na-address") // "naaddress"
|
||||
flag_eth_vpa_address = prefix("eth-vpa-address") // "vpaaddress"
|
||||
flag_eth_ca_address = prefix("eth-ca-address") // "caaddress"
|
||||
// flag_bridge_address = prefix("bridge-address") // "bridgeaddress"
|
||||
|
||||
flag_public_ip = prefix("public-ip") // "publicip"
|
||||
flag_msg_port = prefix("msg-port") // "msgport"
|
||||
flag_ws_msg_port = prefix("ws-msg-port") // "wsmsgport"
|
||||
flag_rpc_port = prefix("rpc-port") // "rpcport"
|
||||
flag_boot_peers = prefix("boot-peers") // "bootpeers"
|
||||
flag_ext_multiaddr = prefix("ext-multiaddr") // "extmultiaddr"
|
||||
flag_tls_cert_filepath = prefix("tls-cert-filepath") // "tlscertfilepath"
|
||||
flag_tls_key_filepath = prefix("tls-key-filepath") // "tlskeyfilepath"
|
||||
// flag_gui_port = prefix("gui-port") // "guiport"
|
||||
)
|
||||
|
||||
func addServerFlags(flags *pflag.FlagSet) {
|
||||
flags.String(flag_pk, "",
|
||||
"name of private key used by the Nitro node",
|
||||
// EnvVars: []string{"SC_PK"},
|
||||
)
|
||||
flags.String(flag_eth_url, "ws://127.0.0.1:8545",
|
||||
"URL of the Ethereum node to connect to",
|
||||
// EnvVars: []string{"CHAIN_URL"},
|
||||
)
|
||||
flags.String(flag_eth_auth_token, "",
|
||||
"bearer token used for auth in requests to the Ethereum chain's RPC endpoint",
|
||||
// EnvVars: []string{"CHAIN_AUTH_TOKEN"},
|
||||
)
|
||||
flags.Uint64(flag_eth_start_block, 0,
|
||||
"Ethereum block number to start listening for Nitro Adjudicator events",
|
||||
// EnvVars: []string{"CHAIN_START_BLOCK"},
|
||||
)
|
||||
flags.String(flag_eth_na_address, "",
|
||||
"Ethereum address of the Nitro Adjudicator contract",
|
||||
)
|
||||
flags.String(flag_eth_vpa_address, "",
|
||||
"Ethereum address of the Virtual Payment App contract",
|
||||
)
|
||||
flags.String(flag_eth_ca_address, "",
|
||||
"Ethereum address of the Consensus App contract",
|
||||
)
|
||||
// flags.String(flag_bridge_address, "",
|
||||
// "Specifies the address of the bridge contract.",
|
||||
// )
|
||||
flags.String(flag_public_ip, "127.0.0.1",
|
||||
"public IP address used for the Nitro message service",
|
||||
// EnvVars: []string{"NITRO_PUBLIC_IP"},
|
||||
)
|
||||
flags.String(flag_ext_multiaddr, "",
|
||||
"additional external multiaddr to advertise",
|
||||
)
|
||||
flags.Int(flag_msg_port, 3005,
|
||||
"TCP port for the Nitro message service",
|
||||
)
|
||||
flags.Int(flag_ws_msg_port, 6005,
|
||||
"WebSocket port for the Nitro message service",
|
||||
)
|
||||
flags.Int(flag_rpc_port, 4005,
|
||||
"TCP port for the Nitro RPC server",
|
||||
)
|
||||
// flags.Int(flag_gui_port, 5005,
|
||||
// "Specifies the tcp port for the Nitro Connect GUI.",
|
||||
// )
|
||||
flags.String(flag_boot_peers, "",
|
||||
"comma-delimited list of peer multiaddrs the messaging service will connect to when initialized",
|
||||
)
|
||||
flags.String(flag_tls_cert_filepath, "", // "./tls/statechannels.org.pem",
|
||||
"filepath to the TLS certificate; if not specified, TLS will not be used with the RPC transport",
|
||||
)
|
||||
flags.String(flag_tls_key_filepath, "", // "./tls/statechannels.org_key.pem",
|
||||
"filepath to the TLS private key; if not specified, TLS will not be used with the RPC transport",
|
||||
)
|
||||
}
|
||||
|
||||
func addClientFlags(flags *pflag.FlagSet) {
|
||||
// TODO: this is only used by "client" (user) nodes
|
||||
flags.String(flag_eth_pk, "",
|
||||
"name of private key to use when interacting with the Ethereum chain",
|
||||
// EnvVars: []string{"CHAIN_PK"},
|
||||
)
|
||||
addServerFlags(flags)
|
||||
}
|
||||
169
server/nitro/p2p.go
Normal file
169
server/nitro/p2p.go
Normal file
@ -0,0 +1,169 @@
|
||||
package nitro
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cometbft/cometbft/p2p"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
nitrop2p "github.com/statechannels/go-nitro/node/engine/messageservice"
|
||||
"github.com/statechannels/go-nitro/protocols"
|
||||
)
|
||||
|
||||
const (
|
||||
P2PMessageChannel = byte(0x80)
|
||||
// SigRequestChannel = byte(0x81)
|
||||
)
|
||||
|
||||
type msgService struct {
|
||||
id string
|
||||
incoming chan nitrop2p.Message
|
||||
outgoing chan nitrop2p.Message
|
||||
|
||||
// dummy channel, we don't need these requests
|
||||
// TODO: make this optional in nitro
|
||||
signreqs chan nitrop2p.SignatureRequest
|
||||
|
||||
reactor *reactor // one reactor per msg service
|
||||
}
|
||||
|
||||
// reactor handles incoming Nitro P2P messages via CometBFT
|
||||
type reactor struct {
|
||||
p2p.BaseReactor
|
||||
|
||||
ms *msgService
|
||||
}
|
||||
|
||||
type streamDesc struct {
|
||||
id byte
|
||||
msgType proto.Message
|
||||
}
|
||||
|
||||
func (sd streamDesc) StreamID() byte { return sd.id }
|
||||
|
||||
// TODO: convert Message to protobuf
|
||||
func (sd streamDesc) MessageType() proto.Message { return sd.msgType }
|
||||
|
||||
// MessageService
|
||||
|
||||
func newMessageService(id string) *msgService {
|
||||
return &msgService{
|
||||
incoming: make(chan nitrop2p.Message),
|
||||
outgoing: make(chan nitrop2p.Message),
|
||||
signreqs: make(chan nitrop2p.SignatureRequest),
|
||||
}
|
||||
}
|
||||
|
||||
func (ms *msgService) P2PMessages() <-chan nitrop2p.Message {
|
||||
return ms.incoming
|
||||
}
|
||||
|
||||
func (ms *msgService) SignRequests() <-chan nitrop2p.SignatureRequest {
|
||||
return ms.signreqs
|
||||
}
|
||||
|
||||
func (ms *msgService) Send(m nitrop2p.Message) error {
|
||||
ms.outgoing <- m
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *msgService) Close() error {
|
||||
close(ms.incoming)
|
||||
close(ms.outgoing)
|
||||
close(ms.signreqs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *msgService) Id() string {
|
||||
return ms.id
|
||||
}
|
||||
|
||||
// Reactor
|
||||
|
||||
func getReactor(ms *msgService) *reactor {
|
||||
if ms.reactor != nil {
|
||||
return ms.reactor
|
||||
}
|
||||
ret := &reactor{ms: ms}
|
||||
ret.BaseReactor = *p2p.NewBaseReactor("nitro-reactor", ret)
|
||||
ms.reactor = ret
|
||||
return ret
|
||||
}
|
||||
|
||||
// StreamDescriptors returns the stream descriptor for Nitro messages.
|
||||
func (r *reactor) StreamDescriptors() []p2p.ChannelDescriptor {
|
||||
return []p2p.ChannelDescriptor{
|
||||
{
|
||||
ID: P2PMessageChannel,
|
||||
MessageType: &P2PMessage{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AddPeer begins sending messages to a peer.
|
||||
func (r *reactor) AddPeer(peer p2p.Peer) {
|
||||
if !r.IsRunning() {
|
||||
return
|
||||
}
|
||||
go r.streamTo(peer)
|
||||
}
|
||||
|
||||
func (r *reactor) streamTo(peer p2p.Peer) {
|
||||
logger := r.Logger.With("peer", peer)
|
||||
// if !peer.HasChannel(P2PMessageChannel) {
|
||||
// logger.Info("Peer does not implement NitroMsgChannel")
|
||||
// return
|
||||
// }
|
||||
|
||||
for {
|
||||
if !peer.IsRunning() || !r.IsRunning() {
|
||||
return
|
||||
}
|
||||
inner_loop:
|
||||
for {
|
||||
select {
|
||||
case msg := <-r.ms.outgoing:
|
||||
encoded, err := msg.Serialize()
|
||||
if err != nil {
|
||||
logger.Error("Failed to serialize message", "msg", msg, "err", err)
|
||||
continue inner_loop
|
||||
}
|
||||
sent := peer.Send(p2p.Envelope{
|
||||
Message: &P2PMessage{Content: encoded},
|
||||
ChannelID: P2PMessageChannel,
|
||||
})
|
||||
if !sent {
|
||||
logger.Error("Failed to send message", "msg", msg) //, "err", err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
break inner_loop
|
||||
}
|
||||
}
|
||||
// time.Sleep()
|
||||
}
|
||||
}
|
||||
|
||||
// Receive handles an envelope received from any connected peer on any registered channel.
|
||||
func (r *reactor) Receive(e p2p.Envelope) {
|
||||
if !r.IsRunning() {
|
||||
r.Logger.Debug("Receive", "src", e.Src, "chId", e.ChannelID)
|
||||
return
|
||||
}
|
||||
switch e.ChannelID {
|
||||
case P2PMessageChannel:
|
||||
switch msg := e.Message.(type) {
|
||||
case *P2PMessage:
|
||||
nitroMsg, err := protocols.DeserializeMessage(msg.Content)
|
||||
if err != nil {
|
||||
r.Logger.Error("Failed to deserialize message", "err", err)
|
||||
r.Switch.StopPeerForError(e.Src, err)
|
||||
return
|
||||
}
|
||||
r.ms.incoming <- nitroMsg
|
||||
default:
|
||||
r.Logger.Error(fmt.Sprintf("Unknown message type: %T", e.Message))
|
||||
}
|
||||
default:
|
||||
r.Logger.Error(fmt.Sprintf("Unknown channel ID: %X", e.ChannelID))
|
||||
}
|
||||
}
|
||||
315
server/nitro/p2p.pb.go
Normal file
315
server/nitro/p2p.pb.go
Normal file
@ -0,0 +1,315 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: cerc/nitro/v1/p2p.proto
|
||||
|
||||
package nitro
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/cosmos/gogoproto/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type P2PMessage struct {
|
||||
Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"`
|
||||
}
|
||||
|
||||
func (m *P2PMessage) Reset() { *m = P2PMessage{} }
|
||||
func (m *P2PMessage) String() string { return proto.CompactTextString(m) }
|
||||
func (*P2PMessage) ProtoMessage() {}
|
||||
func (*P2PMessage) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_97350824263b9206, []int{0}
|
||||
}
|
||||
func (m *P2PMessage) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *P2PMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_P2PMessage.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *P2PMessage) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_P2PMessage.Merge(m, src)
|
||||
}
|
||||
func (m *P2PMessage) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *P2PMessage) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_P2PMessage.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_P2PMessage proto.InternalMessageInfo
|
||||
|
||||
func (m *P2PMessage) GetContent() string {
|
||||
if m != nil {
|
||||
return m.Content
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*P2PMessage)(nil), "cerc.nitro.v1.P2PMessage")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("cerc/nitro/v1/p2p.proto", fileDescriptor_97350824263b9206) }
|
||||
|
||||
var fileDescriptor_97350824263b9206 = []byte{
|
||||
// 162 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0x4e, 0x2d, 0x4a,
|
||||
0xd6, 0xcf, 0xcb, 0x2c, 0x29, 0xca, 0xd7, 0x2f, 0x33, 0xd4, 0x2f, 0x30, 0x2a, 0xd0, 0x2b, 0x28,
|
||||
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x05, 0x49, 0xe8, 0x81, 0x25, 0xf4, 0xca, 0x0c, 0x95, 0xd4, 0xb8,
|
||||
0xb8, 0x02, 0x8c, 0x02, 0x7c, 0x53, 0x8b, 0x8b, 0x13, 0xd3, 0x53, 0x85, 0x24, 0xb8, 0xd8, 0x93,
|
||||
0xf3, 0xf3, 0x4a, 0x52, 0xf3, 0x4a, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x60, 0x5c, 0x27,
|
||||
0xa7, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63,
|
||||
0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x48, 0xcf, 0x2c, 0xd1,
|
||||
0x2b, 0x4b, 0x49, 0xd2, 0x2b, 0xc9, 0xd7, 0x07, 0x99, 0xad, 0x9b, 0x99, 0xaf, 0x9f, 0x93, 0x98,
|
||||
0x9c, 0x9f, 0x97, 0x99, 0x9c, 0xa2, 0x5f, 0x9c, 0x5a, 0x54, 0x96, 0x5a, 0x04, 0x71, 0x47, 0x12,
|
||||
0x1b, 0xd8, 0x05, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x79, 0x5d, 0x6d, 0x7c, 0x9c, 0x00,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *P2PMessage) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *P2PMessage) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *P2PMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Content) > 0 {
|
||||
i -= len(m.Content)
|
||||
copy(dAtA[i:], m.Content)
|
||||
i = encodeVarintP2P(dAtA, i, uint64(len(m.Content)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintP2P(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovP2P(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *P2PMessage) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Content)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovP2P(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovP2P(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozP2P(x uint64) (n int) {
|
||||
return sovP2P(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *P2PMessage) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowP2P
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: P2PMessage: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: P2PMessage: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Content", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowP2P
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthP2P
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthP2P
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Content = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipP2P(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthP2P
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipP2P(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowP2P
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowP2P
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowP2P
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthP2P
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupP2P
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthP2P
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthP2P = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowP2P = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupP2P = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
207
server/nitro/server.go
Normal file
207
server/nitro/server.go
Normal file
@ -0,0 +1,207 @@
|
||||
package nitro
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/statechannels/go-nitro/node"
|
||||
"github.com/statechannels/go-nitro/node/engine"
|
||||
"github.com/statechannels/go-nitro/node/engine/chainservice"
|
||||
"github.com/statechannels/go-nitro/node/engine/store"
|
||||
nitrotypes "github.com/statechannels/go-nitro/types"
|
||||
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/log"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
serverName = "nitro"
|
||||
)
|
||||
|
||||
var (
|
||||
_ serverv2.ServerComponent[transaction.Tx] = (*Server)(nil)
|
||||
_ serverv2.HasCLICommands = (*Server)(nil)
|
||||
_ serverv2.HasStartFlags = (*Server)(nil)
|
||||
_ serverv2.HasConfig = (*Server)(nil)
|
||||
// _ serverv2.ConfigWriter = (*Server)(nil)
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// - move multisig stuff into here. DKG is init'd from eth key.
|
||||
// - server.SetParticipants() updates DKG members
|
||||
// - onboarding module calls this
|
||||
// - onboarding sets deals?
|
||||
|
||||
type Server struct {
|
||||
*node.Node
|
||||
ms *msgService
|
||||
|
||||
logger log.Logger
|
||||
config *Config
|
||||
storeDir string // path to Nitro store directory
|
||||
|
||||
ethAddress common.Address
|
||||
stateChannelAddress nitrotypes.ParticipantAddress
|
||||
}
|
||||
|
||||
func NewServer(logger log.Logger, globalConfig server.ConfigMap, kr keyring.Keyring) (*Server, error) {
|
||||
home, _ := globalConfig[serverv2.FlagHome].(string)
|
||||
cfg, err := UnmarshalConfig(globalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &Server{
|
||||
config: cfg,
|
||||
storeDir: filepath.Join(home, "nitro"),
|
||||
}
|
||||
s.logger = logger.With(log.ModuleKey, s.Name())
|
||||
return s, s.init(kr)
|
||||
}
|
||||
|
||||
func (s *Server) init(kr keyring.Keyring) error {
|
||||
c := s.config
|
||||
|
||||
var ethkey cryptotypes.PrivKey
|
||||
if c.EthPk != "" {
|
||||
var err error
|
||||
ethkey, err = utils.ExtractPrivateKey(kr, c.EthPk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// TODO for server, inject signer callback into nitro node instead of naked privkey
|
||||
// multisig will be negotiated over ABCI, then funds are sent via custodian contract
|
||||
s.logger.Warn("(DEV) using fake Laconic custodian Ethereum private key")
|
||||
ethkey = &LaconicCustodianPrivKey
|
||||
}
|
||||
|
||||
sckey, err := utils.ExtractPrivateKey(kr, c.Pk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storeOpts := store.StoreOpts{
|
||||
PkBytes: sckey.Bytes(),
|
||||
UseDurableStore: true,
|
||||
DurableStoreFolder: s.storeDir,
|
||||
}
|
||||
chainOpts := chainservice.ChainOpts{
|
||||
ChainUrl: c.EthUrl,
|
||||
ChainStartBlockNum: c.EthStartBlock,
|
||||
ChainAuthToken: c.EthAuthToken,
|
||||
// TODO see above
|
||||
ChainPk: hex.EncodeToString(ethkey.Bytes()),
|
||||
NaAddress: common.HexToAddress(c.EthNaAddress),
|
||||
VpaAddress: common.HexToAddress(c.EthVpaAddress),
|
||||
CaAddress: common.HexToAddress(c.EthCaAddress),
|
||||
}
|
||||
// inject SDK logger into slog, which Nitro uses
|
||||
loggerImpl, ok := s.logger.Impl().(*slog.Logger)
|
||||
if !ok {
|
||||
s.logger.Warn("logger does not have slog implementation")
|
||||
}
|
||||
slog.SetDefault(loggerImpl)
|
||||
|
||||
s.logger.Info("Initializing chain service")
|
||||
|
||||
store, err := store.NewStore(storeOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Compare chainOpts.ChainStartBlock to lastBlockNum seen in store. The larger of the two
|
||||
// gets passed as an argument when creating NewEthChainService
|
||||
storeBlockNum, err := store.GetLastBlockNumSeen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if storeBlockNum > chainOpts.ChainStartBlockNum {
|
||||
chainOpts.ChainStartBlockNum = storeBlockNum
|
||||
}
|
||||
chain, err := chainservice.NewL1ChainService(chainOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// note: utils.EthAddressFromPubKey expects uncompressed keys
|
||||
ethPubkey, err := crypto.DecompressPubkey(ethkey.PubKey().Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.ms = newMessageService(store.GetAddress().String())
|
||||
s.Node = node.New(s.ms, chain, store, &engine.PermissivePolicy{})
|
||||
s.ethAddress = crypto.PubkeyToAddress(*ethPubkey)
|
||||
s.stateChannelAddress = *store.GetAddress()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Name() string {
|
||||
return serverName
|
||||
}
|
||||
|
||||
func (s *Server) Start(ctx context.Context) error {
|
||||
s.logger.Info("starting Nitro server",
|
||||
"rpc-port", fmt.Sprintf("http://%s:%d", s.config.PublicIp, s.config.RpcPort))
|
||||
s.Node.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Stop(context.Context) error {
|
||||
return s.Close()
|
||||
}
|
||||
|
||||
func (s *Server) Config() any {
|
||||
if s.config == nil {
|
||||
return DefaultConfig()
|
||||
}
|
||||
return s.config
|
||||
}
|
||||
|
||||
func (s *Server) StartCmdFlags() *pflag.FlagSet {
|
||||
flags := pflag.NewFlagSet(s.Name(), pflag.ExitOnError)
|
||||
addServerFlags(flags)
|
||||
return flags
|
||||
}
|
||||
|
||||
// func (s *Server) WriteConfig(path string) error
|
||||
|
||||
func (s *Server) CLICommands() serverv2.CLIConfig {
|
||||
return serverv2.CLIConfig{
|
||||
Commands: []*cobra.Command{
|
||||
s.OpenChannelCmd(),
|
||||
},
|
||||
// Queries: []*cobra.Command{},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) CometReactor() *reactor {
|
||||
return getReactor(s.ms)
|
||||
}
|
||||
|
||||
func UnmarshalConfig(cfg map[string]any) (*Config, error) {
|
||||
config := DefaultConfig()
|
||||
if err := serverv2.UnmarshalSubConfig(cfg, serverName, config); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %T: %w", config, err)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// func ProvideServer(logger log.Logger, globalConfig runtime.GlobalConfig, kr keyring.Keyring) (*Server, error) {
|
||||
// home, _ := globalConfig[serverv2.FlagHome].(string)
|
||||
// config, err := UnmarshalConfig(globalConfig)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return NewServer(logger, config, kr, filepath.Join(home, "nitro"))
|
||||
// }
|
||||
19
server/nitro/service.go
Normal file
19
server/nitro/service.go
Normal file
@ -0,0 +1,19 @@
|
||||
package nitro
|
||||
|
||||
import (
|
||||
"github.com/cometbft/cometbft/types"
|
||||
"github.com/statechannels/go-nitro/channel/state/outcome"
|
||||
"github.com/statechannels/go-nitro/protocols/directfund"
|
||||
"github.com/statechannels/go-nitro/protocols/virtualfund"
|
||||
)
|
||||
|
||||
// Service represents a service which triggers Nitro state channel actions
|
||||
type Service interface {
|
||||
// CreatePaymentChannel creates a new virtual payment channel with the specified intermediaries,
|
||||
// counterparty, ChallengeDuration, and outcome
|
||||
CreatePaymentChannel(intermediaries []types.Address, counterparty types.Address, ChallengeDuration uint32, outcome outcome.Exit) (virtualfund.ObjectiveResponse, error)
|
||||
|
||||
// CreateLedgerChannel creates a new ledger channel with the specified counterparty,
|
||||
// ChallengeDuration, and outcome
|
||||
CreateLedgerChannel(counterparty types.Address, ChallengeDuration uint32, outcome outcome.Exit) (directfund.ObjectiveResponse, error)
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package auction
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/tests/e2e"
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
)
|
||||
|
||||
func TestAuctionE2ETestSuite(t *testing.T) {
|
||||
cfg := network.DefaultConfig(e2e.NewTestNetworkFixture)
|
||||
cfg.NumValidators = 1
|
||||
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
||||
@ -1,263 +0,0 @@
|
||||
package auction
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
|
||||
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
)
|
||||
|
||||
const (
|
||||
randomAuctionId = "randomAuctionId"
|
||||
randomBidderAddress = "randomBidderAddress"
|
||||
randomOwnerAddress = "randomOwnerAddress"
|
||||
)
|
||||
|
||||
func (ets *E2ETestSuite) TestQueryParamsGrpc() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/auction/v1/params", val.APIAddress)
|
||||
|
||||
ets.Run("valid request to get auction params", func() {
|
||||
resp, err := testutil.GetRequest(reqURL)
|
||||
ets.Require().NoError(err)
|
||||
|
||||
var params auctiontypes.QueryParamsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, ¶ms)
|
||||
|
||||
sr.NoError(err)
|
||||
sr.Equal(*params.GetParams(), auctiontypes.DefaultParams())
|
||||
})
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGetAllAuctionsGrpc() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/auction/v1/auctions", val.APIAddress)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
url string
|
||||
errorMsg string
|
||||
isErrorExpected bool
|
||||
}{
|
||||
{
|
||||
"invalid request to get all auctions",
|
||||
reqURL + randomAuctionId,
|
||||
"",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid request to get all auctions",
|
||||
reqURL,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.msg, func() {
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
if tc.isErrorExpected {
|
||||
sr.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
var auctions auctiontypes.QueryAuctionsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auctions)
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(auctions.Auctions.Auctions))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGetAuctionGrpc() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/auction/v1/auctions/", val.APIAddress)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
url string
|
||||
errorMsg string
|
||||
isErrorExpected bool
|
||||
preRun func() string
|
||||
}{
|
||||
{
|
||||
"invalid request to get an auction",
|
||||
reqURL + randomAuctionId,
|
||||
"",
|
||||
true,
|
||||
func() string { return "" },
|
||||
},
|
||||
{
|
||||
"valid request to get an auction",
|
||||
reqURL,
|
||||
"",
|
||||
false,
|
||||
func() string { return ets.defaultAuctionId },
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.msg, func() {
|
||||
auctionId := tc.preRun()
|
||||
resp, err := testutil.GetRequest(tc.url + auctionId)
|
||||
if tc.isErrorExpected {
|
||||
sr.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
var auction auctiontypes.QueryGetAuctionResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auction)
|
||||
sr.NoError(err)
|
||||
sr.Equal(auctionId, auction.Auction.Id)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGetBidsGrpc() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/auction/v1/bids/", val.APIAddress)
|
||||
testCases := []struct {
|
||||
msg string
|
||||
url string
|
||||
errorMsg string
|
||||
isErrorExpected bool
|
||||
preRun func() string
|
||||
}{
|
||||
{
|
||||
"invalid request to get all bids",
|
||||
reqURL,
|
||||
"",
|
||||
true,
|
||||
func() string { return "" },
|
||||
},
|
||||
{
|
||||
"valid request to get all bids",
|
||||
reqURL,
|
||||
"",
|
||||
false,
|
||||
func() string { return ets.createAuctionAndBid(false, true) },
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.msg, func() {
|
||||
auctionId := tc.preRun()
|
||||
tc.url += auctionId
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
if tc.isErrorExpected {
|
||||
sr.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
var bids auctiontypes.QueryGetBidsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bids)
|
||||
sr.NoError(err)
|
||||
sr.Equal(auctionId, bids.Bids[0].AuctionId)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGetBidGrpc() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/auction/v1/bids/", val.APIAddress)
|
||||
testCases := []struct {
|
||||
msg string
|
||||
url string
|
||||
errorMsg string
|
||||
isErrorExpected bool
|
||||
preRun func() string
|
||||
}{
|
||||
{
|
||||
"invalid request to get bid",
|
||||
reqURL,
|
||||
"",
|
||||
true,
|
||||
func() string { return randomAuctionId },
|
||||
},
|
||||
{
|
||||
"valid request to get bid",
|
||||
reqURL,
|
||||
"",
|
||||
false,
|
||||
func() string { return ets.createAuctionAndBid(false, true) },
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.msg, func() {
|
||||
auctionId := tc.preRun()
|
||||
tc.url += auctionId + "/" + bidderAddress
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
|
||||
if tc.isErrorExpected {
|
||||
sr.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
var bid auctiontypes.QueryGetBidResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bid)
|
||||
sr.NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGetAuctionsByOwnerGrpc() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/auction/v1/by-owner/", val.APIAddress)
|
||||
testCases := []struct {
|
||||
msg string
|
||||
url string
|
||||
errorMsg string
|
||||
isErrorExpected bool
|
||||
}{
|
||||
{
|
||||
"invalid request to get auctions by owner",
|
||||
reqURL,
|
||||
"",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid request to get auctions by owner",
|
||||
fmt.Sprintf("%s/%s", reqURL, ownerAddress),
|
||||
"",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.msg, func() {
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
if tc.isErrorExpected {
|
||||
sr.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
var auctions auctiontypes.QueryAuctionsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auctions)
|
||||
sr.NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestQueryBalanceGrpc() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/auction/v1/balance", val.APIAddress)
|
||||
msg := "valid request to get the auction module balance"
|
||||
|
||||
ets.createAuctionAndBid(false, true)
|
||||
|
||||
ets.Run(msg, func() {
|
||||
resp, err := testutil.GetRequest(reqURL)
|
||||
sr.NoError(err)
|
||||
|
||||
var response auctiontypes.QueryGetAuctionModuleBalanceResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(response.GetBalance()))
|
||||
})
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
package auction
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
|
||||
types "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
"git.vdb.to/cerc-io/laconicd/x/auction/client/cli"
|
||||
)
|
||||
|
||||
var queryJSONFlag = []string{fmt.Sprintf("--%s=json", flags.FlagOutput)}
|
||||
|
||||
func (ets *E2ETestSuite) TestGetCmdList() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
createAuction bool
|
||||
}{
|
||||
{
|
||||
"list auctions when no auctions exist",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"list auctions after creating an auction",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
ets.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag)
|
||||
sr.NoError(err)
|
||||
var auctions types.QueryAuctionsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &auctions)
|
||||
sr.NoError(err)
|
||||
if test.createAuction {
|
||||
sr.NotZero(len(auctions.Auctions.Auctions))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,151 +0,0 @@
|
||||
package auction
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
laconictestcli "git.vdb.to/cerc-io/laconicd/testutil/cli"
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
types "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
"git.vdb.to/cerc-io/laconicd/x/auction/client/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
ownerAccount = "owner"
|
||||
bidderAccount = "bidder"
|
||||
ownerAddress string
|
||||
bidderAddress string
|
||||
)
|
||||
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
|
||||
defaultAuctionId string
|
||||
}
|
||||
|
||||
func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
return &E2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) SetupSuite() { //nolint: all
|
||||
sr := ets.Require()
|
||||
ets.T().Log("setting up e2e test suite")
|
||||
|
||||
var err error
|
||||
|
||||
ets.network, err = network.New(ets.T(), ets.T().TempDir(), ets.cfg)
|
||||
sr.NoError(err)
|
||||
|
||||
_, err = ets.network.WaitForHeight(1)
|
||||
sr.NoError(err)
|
||||
|
||||
// setting up random owner and bidder accounts
|
||||
ets.createAccountWithBalance(ownerAccount, &ownerAddress)
|
||||
ets.createAccountWithBalance(bidderAccount, &bidderAddress)
|
||||
|
||||
ets.defaultAuctionId = ets.createAuctionAndBid(true, false)
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TearDownSuite() {
|
||||
ets.T().Log("tearing down integration test suite")
|
||||
ets.network.Cleanup()
|
||||
|
||||
ets.cleanupBidFiles()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createAccountWithBalance(accountName string, accountAddress *string) {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||
sr.NoError(err)
|
||||
|
||||
newAddr, _ := info.GetAddress()
|
||||
out, err := clitestutil.MsgSendExec(
|
||||
val.ClientCtx,
|
||||
val.Address,
|
||||
newAddr,
|
||||
sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(200000))),
|
||||
addresscodec.NewBech32Codec("laconic"),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(10))).String()),
|
||||
)
|
||||
sr.NoError(err)
|
||||
|
||||
var response sdk.TxResponse
|
||||
sr.NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, response.TxHash, 0))
|
||||
|
||||
*accountAddress = newAddr.String()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createAuctionAndBid(createAuction, createBid bool) string {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
auctionId := ""
|
||||
|
||||
if createAuction {
|
||||
auctionArgs := []string{
|
||||
types.AuctionKindVickrey,
|
||||
sampleCommitTime, sampleRevealTime,
|
||||
fmt.Sprintf("10%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("10%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("100%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("0%s", ets.cfg.BondDenom),
|
||||
"0",
|
||||
}
|
||||
|
||||
resp, err := ets.executeTx(cli.GetCmdCreateAuction(), auctionArgs, ownerAccount)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, resp.TxHash, 0))
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag)
|
||||
sr.NoError(err)
|
||||
var queryResponse types.QueryAuctionsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||
sr.NoError(err)
|
||||
auctionId = queryResponse.Auctions.Auctions[0].Id
|
||||
} else {
|
||||
auctionId = ets.defaultAuctionId
|
||||
}
|
||||
|
||||
if createBid {
|
||||
bidArgs := []string{auctionId, fmt.Sprintf("200%s", ets.cfg.BondDenom)}
|
||||
resp, err := ets.executeTx(cli.GetCmdCommitBid(), bidArgs, bidderAccount)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, resp.TxHash, 0))
|
||||
}
|
||||
|
||||
return auctionId
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) cleanupBidFiles() {
|
||||
matches, err := filepath.Glob(fmt.Sprintf("%s-*.json", bidderAccount))
|
||||
if err != nil {
|
||||
ets.T().Errorf("Error matching bidder files: %v\n", err)
|
||||
}
|
||||
|
||||
for _, match := range matches {
|
||||
err := os.Remove(match)
|
||||
if err != nil {
|
||||
ets.T().Errorf("Error removing bidder file: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
package auction
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
laconictestcli "git.vdb.to/cerc-io/laconicd/testutil/cli"
|
||||
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
"git.vdb.to/cerc-io/laconicd/x/auction/client/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
sampleCommitTime = "90s"
|
||||
sampleRevealTime = "5s"
|
||||
placeholderAuctionId = "placeholder_auction_id"
|
||||
)
|
||||
|
||||
func (ets *E2ETestSuite) TestTxCommitBid() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
testCases := []struct {
|
||||
msg string
|
||||
args []string
|
||||
createAuction bool
|
||||
}{
|
||||
{
|
||||
"commit bid with missing args",
|
||||
[]string{fmt.Sprintf("200%s", ets.cfg.BondDenom)},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"commit bid with valid args",
|
||||
[]string{
|
||||
placeholderAuctionId,
|
||||
fmt.Sprintf("200%s", ets.cfg.BondDenom),
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
ets.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
if test.createAuction {
|
||||
auctionArgs := []string{
|
||||
auctiontypes.AuctionKindVickrey,
|
||||
sampleCommitTime, sampleRevealTime,
|
||||
fmt.Sprintf("10%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("10%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("100%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("0%s", ets.cfg.BondDenom),
|
||||
"0",
|
||||
}
|
||||
|
||||
resp, err := ets.executeTx(cli.GetCmdCreateAuction(), auctionArgs, ownerAccount)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, resp.TxHash, 0))
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(),
|
||||
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)})
|
||||
sr.NoError(err)
|
||||
var queryResponse auctiontypes.QueryAuctionsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||
sr.NoError(err)
|
||||
sr.NotNil(queryResponse.GetAuctions())
|
||||
test.args[0] = queryResponse.GetAuctions().Auctions[0].Id
|
||||
}
|
||||
|
||||
resp, err := ets.executeTx(cli.GetCmdCommitBid(), test.args, bidderAccount)
|
||||
if test.createAuction {
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, resp.TxHash, 0))
|
||||
} else {
|
||||
sr.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) executeTx(cmd *cobra.Command, args []string, caller string) (sdk.TxResponse, error) {
|
||||
val := ets.network.Validators[0]
|
||||
additionalArgs := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, caller),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
args = append(args, additionalArgs...)
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
|
||||
if err != nil {
|
||||
return sdk.TxResponse{}, err
|
||||
}
|
||||
|
||||
var resp sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp)
|
||||
if err != nil {
|
||||
return sdk.TxResponse{}, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package bond
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/tests/e2e"
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
)
|
||||
|
||||
func TestBondE2ETestSuite(t *testing.T) {
|
||||
cfg := network.DefaultConfig(e2e.NewTestNetworkFixture)
|
||||
cfg.NumValidators = 1
|
||||
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
||||
@ -1,183 +0,0 @@
|
||||
package bond
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
)
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCGetParams() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/bond/v1/params", val.APIAddress)
|
||||
|
||||
resp, err := testutil.GetRequest(reqURL)
|
||||
ets.Require().NoError(err)
|
||||
|
||||
var params bondtypes.QueryParamsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, ¶ms)
|
||||
|
||||
sr.NoError(err)
|
||||
sr.Equal(params.GetParams().MaxBondAmount, bondtypes.DefaultParams().MaxBondAmount)
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCGetBonds() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/bond/v1/bonds", val.APIAddress)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expErr bool
|
||||
errorMsg string
|
||||
preRun func() string
|
||||
}{
|
||||
{
|
||||
"invalid request with headers",
|
||||
reqURL + "asdasdas",
|
||||
true,
|
||||
"",
|
||||
func() string { return "" },
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqURL,
|
||||
false,
|
||||
"",
|
||||
func() string { return ets.createBond() },
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun()
|
||||
|
||||
resp, _ := testutil.GetRequest(tc.url)
|
||||
if tc.expErr {
|
||||
sr.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response bondtypes.QueryBondsResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(response.GetBonds()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCGetBondsByOwner() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/bond/v1/by-owner/%s"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expErr bool
|
||||
preRun func() string
|
||||
}{
|
||||
{
|
||||
"empty list",
|
||||
fmt.Sprintf(reqURL, "asdasd"),
|
||||
true,
|
||||
func() string { return "" },
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
fmt.Sprintf(reqURL, ets.accountAddress),
|
||||
false,
|
||||
func() string { return ets.createBond() },
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun()
|
||||
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.Require().NoError(err)
|
||||
|
||||
var bonds bondtypes.QueryGetBondsByOwnerResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bonds)
|
||||
sr.NoError(err)
|
||||
if tc.expErr {
|
||||
sr.Empty(bonds.GetBonds())
|
||||
} else {
|
||||
bondsList := bonds.GetBonds()
|
||||
sr.NotZero(len(bondsList))
|
||||
sr.Equal(ets.accountAddress, bondsList[0].GetOwner())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCGetBondById() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/bond/v1/bonds/%s"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expErr bool
|
||||
preRun func() string
|
||||
}{
|
||||
{
|
||||
"invalid request",
|
||||
fmt.Sprintf(reqURL, "asdadad"),
|
||||
true,
|
||||
func() string { return "" },
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqURL,
|
||||
false,
|
||||
func() string { return ets.createBond() },
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
var bondId string
|
||||
if !tc.expErr {
|
||||
bondId = tc.preRun()
|
||||
tc.url = fmt.Sprintf(reqURL, bondId)
|
||||
}
|
||||
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.Require().NoError(err)
|
||||
|
||||
var bonds bondtypes.QueryGetBondByIdResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &bonds)
|
||||
|
||||
if tc.expErr {
|
||||
sr.Empty(bonds.GetBond().GetId())
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
sr.NotZero(bonds.GetBond().GetId())
|
||||
sr.Equal(bonds.GetBond().GetId(), bondId)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCGetBondModuleBalance() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := fmt.Sprintf("%s/cerc/bond/v1/balance", val.APIAddress)
|
||||
|
||||
// creating the bond
|
||||
ets.createBond()
|
||||
|
||||
ets.Run("valid request", func() {
|
||||
resp, err := testutil.GetRequest(reqURL)
|
||||
sr.NoError(err)
|
||||
|
||||
var response bondtypes.QueryGetBondModuleBalanceResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
|
||||
sr.NoError(err)
|
||||
sr.False(response.GetBalance().IsZero())
|
||||
})
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
package bond
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
"git.vdb.to/cerc-io/laconicd/x/bond/client/cli"
|
||||
)
|
||||
|
||||
func (ets *E2ETestSuite) TestGetQueryBondList() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
createBond bool
|
||||
preRun func()
|
||||
}{
|
||||
{
|
||||
"create and get bond lists",
|
||||
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
|
||||
true,
|
||||
func() {
|
||||
ets.createBond()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||
clientCtx := val.ClientCtx
|
||||
if tc.createBond {
|
||||
tc.preRun()
|
||||
}
|
||||
|
||||
cmd := cli.GetQueryBondList()
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||
sr.NoError(err)
|
||||
var queryResponse bondtypes.QueryBondsResponse
|
||||
err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(queryResponse.GetBonds()))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,125 +0,0 @@
|
||||
package bond
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
laconictestcli "git.vdb.to/cerc-io/laconicd/testutil/cli"
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
"git.vdb.to/cerc-io/laconicd/x/bond/client/cli"
|
||||
)
|
||||
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
|
||||
accountName string
|
||||
accountAddress string
|
||||
}
|
||||
|
||||
func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
return &E2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) SetupSuite() { //nolint: all
|
||||
sr := ets.Require()
|
||||
ets.T().Log("setting up e2e test suite")
|
||||
|
||||
var err error
|
||||
|
||||
ets.network, err = network.New(ets.T(), ets.T().TempDir(), ets.cfg)
|
||||
sr.NoError(err)
|
||||
|
||||
_, err = ets.network.WaitForHeight(1)
|
||||
sr.NoError(err)
|
||||
|
||||
// setting up random account
|
||||
ets.accountName = "accountName"
|
||||
ets.createAccountWithBalance(ets.accountName, &ets.accountAddress)
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TearDownSuite() {
|
||||
ets.T().Log("tearing down e2e test suite")
|
||||
ets.network.Cleanup()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createAccountWithBalance(accountName string, accountAddress *string) {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||
sr.NoError(err)
|
||||
|
||||
newAddr, _ := info.GetAddress()
|
||||
out, err := clitestutil.MsgSendExec(
|
||||
val.ClientCtx,
|
||||
val.Address,
|
||||
newAddr,
|
||||
sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(200000))),
|
||||
addresscodec.NewBech32Codec("laconic"),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(10))).String()),
|
||||
)
|
||||
sr.NoError(err)
|
||||
|
||||
var response sdk.TxResponse
|
||||
sr.NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, response.TxHash, 0))
|
||||
|
||||
*accountAddress = newAddr.String()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createBond() string {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
createBondCmd := cli.NewCreateBondCmd()
|
||||
args := []string{
|
||||
fmt.Sprintf("10%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, createBondCmd, args)
|
||||
sr.NoError(err)
|
||||
|
||||
var d sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.Zero(d.Code)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, d.TxHash, 0))
|
||||
|
||||
// getting the bonds list and returning the bond-id
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := cli.GetQueryBondList()
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
}
|
||||
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
var queryResponse bondtypes.QueryBondsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||
sr.NoError(err)
|
||||
|
||||
// extract bond id from bonds list
|
||||
bonds := queryResponse.GetBonds()
|
||||
sr.NotEmpty(bonds)
|
||||
|
||||
return queryResponse.GetBonds()[0].GetId()
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
package bond
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/x/bond/client/cli"
|
||||
)
|
||||
|
||||
func (ets *E2ETestSuite) TestTxCreateBond() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
"without deposit",
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"create bond",
|
||||
[]string{
|
||||
fmt.Sprintf("10%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := cli.NewCreateBondCmd()
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||
if tc.err {
|
||||
sr.Error(err)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
var d sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.Nil(err)
|
||||
sr.NoError(err)
|
||||
sr.Zero(d.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
pruningtypes "cosmossdk.io/store/pruning/types"
|
||||
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
"github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
|
||||
laconicApp "git.vdb.to/cerc-io/laconicd/app"
|
||||
auctionmodule "git.vdb.to/cerc-io/laconicd/x/auction/module"
|
||||
bondmodule "git.vdb.to/cerc-io/laconicd/x/bond/module"
|
||||
registrymodule "git.vdb.to/cerc-io/laconicd/x/registry/module"
|
||||
|
||||
_ "git.vdb.to/cerc-io/laconicd/app/params" // import for side-effects (see init)
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
)
|
||||
|
||||
// NewTestNetworkFixture returns a new LaconicApp AppConstructor for network simulation tests
|
||||
func NewTestNetworkFixture() network.TestFixture {
|
||||
dir, err := os.MkdirTemp("", "laconic")
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed creating temporary directory: %v", err))
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
app, err := laconicApp.NewLaconicApp(log.NewNopLogger(), dbm.NewMemDB(), nil, true, simtestutil.NewAppOptionsWithFlagHome(dir))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to create laconic app: %v", err))
|
||||
}
|
||||
|
||||
appCtr := func(val network.ValidatorI) servertypes.Application {
|
||||
app, err := laconicApp.NewLaconicApp(
|
||||
val.GetCtx().Logger, dbm.NewMemDB(), nil, true,
|
||||
simtestutil.NewAppOptionsWithFlagHome(val.GetCtx().Config.RootDir),
|
||||
bam.SetPruning(pruningtypes.NewPruningOptionsFromString(val.GetAppConfig().Pruning)),
|
||||
bam.SetMinGasPrices(val.GetAppConfig().MinGasPrices),
|
||||
bam.SetChainID(val.GetCtx().Viper.GetString(flags.FlagChainID)),
|
||||
)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed creating temporary directory: %v", err))
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
return network.TestFixture{
|
||||
AppConstructor: appCtr,
|
||||
GenesisState: app.DefaultGenesis(),
|
||||
EncodingConfig: testutil.MakeTestEncodingConfig(
|
||||
auth.AppModuleBasic{},
|
||||
bank.AppModuleBasic{},
|
||||
staking.AppModuleBasic{},
|
||||
auctionmodule.AppModule{},
|
||||
bondmodule.AppModule{},
|
||||
registrymodule.AppModule{},
|
||||
),
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/tests/e2e"
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
)
|
||||
|
||||
func TestRegistryE2ETestSuite(t *testing.T) {
|
||||
cfg := network.DefaultConfig(e2e.NewTestNetworkFixture)
|
||||
cfg.NumValidators = 1
|
||||
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
||||
@ -1,429 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
|
||||
registrytypes "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
"git.vdb.to/cerc-io/laconicd/x/registry/client/cli"
|
||||
)
|
||||
|
||||
const badPath = "/asdasd"
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryParams() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/registry/v1/params"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
"invalid request",
|
||||
reqURL + badPath,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqURL,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
require := ets.Require()
|
||||
if tc.expectErr {
|
||||
require.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryParamsResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
|
||||
params := registrytypes.DefaultParams()
|
||||
ets.updateParams(¶ms)
|
||||
sr.Equal(params.String(), response.GetParams().String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryWhoIs() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqUrl := val.APIAddress + "/cerc/registry/v1/whois/%s"
|
||||
authorityName := "QueryWhoIS"
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
preRun func(authorityName string)
|
||||
}{
|
||||
{
|
||||
"invalid url",
|
||||
reqUrl + badPath,
|
||||
true,
|
||||
"",
|
||||
func(authorityName string) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqUrl,
|
||||
false,
|
||||
"",
|
||||
func(authorityName string) { ets.reserveName(authorityName) },
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun(authorityName)
|
||||
tc.url = fmt.Sprintf(tc.url, authorityName)
|
||||
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
require := ets.Require()
|
||||
if tc.expectErr {
|
||||
require.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryWhoisResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
sr.Equal(registrytypes.AuthorityActive, response.GetNameAuthority().Status)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryLookup() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/registry/v1/lookup"
|
||||
authorityName := "QueryLookUp"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
preRun func(authorityName string)
|
||||
}{
|
||||
{
|
||||
"invalid url",
|
||||
reqURL + badPath,
|
||||
true,
|
||||
"",
|
||||
func(authorityName string) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
fmt.Sprintf(reqURL+"?lrn=lrn://%s/", authorityName),
|
||||
false,
|
||||
"",
|
||||
func(authorityName string) {
|
||||
// create name record
|
||||
ets.createNameRecord(authorityName)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun(authorityName)
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
if tc.expectErr {
|
||||
sr.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryLookupLrnResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(response.Name.Latest.Id))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryListRecords() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqUrl := val.APIAddress + "/cerc/registry/v1/records"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
preRun func(bondId string)
|
||||
}{
|
||||
{
|
||||
"invalid url",
|
||||
reqUrl + badPath,
|
||||
true,
|
||||
"",
|
||||
func(bondId string) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqUrl,
|
||||
false,
|
||||
"",
|
||||
func(bondId string) { ets.createRecord(bondId) },
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun(ets.bondId)
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
require := ets.Require()
|
||||
if tc.expectErr {
|
||||
require.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryRecordsResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(response.GetRecords()))
|
||||
sr.Equal(ets.bondId, response.GetRecords()[0].GetBondId())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryGetRecordById() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/registry/v1/records/%s"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
preRun func(bondId string) string
|
||||
}{
|
||||
{
|
||||
"invalid url",
|
||||
reqURL + badPath,
|
||||
true,
|
||||
"",
|
||||
func(bondId string) string {
|
||||
return ""
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqURL,
|
||||
false,
|
||||
"",
|
||||
func(bondId string) string {
|
||||
// creating the record
|
||||
ets.createRecord(bondId)
|
||||
|
||||
// list the records
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := cli.GetCmdList()
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
}
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
var records []registrytypes.ReadableRecord
|
||||
err = json.Unmarshal(out.Bytes(), &records)
|
||||
sr.NoError(err)
|
||||
return records[0].Id
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
recordId := tc.preRun(ets.bondId)
|
||||
tc.url = fmt.Sprintf(reqURL, recordId)
|
||||
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
require := ets.Require()
|
||||
if tc.expectErr {
|
||||
require.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryGetRecordResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
record := response.GetRecord()
|
||||
sr.NotZero(len(record.GetId()))
|
||||
sr.Equal(record.GetId(), recordId)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryGetRecordByBondId() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/registry/v1/records-by-bond-id/%s"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
preRun func(bondId string)
|
||||
}{
|
||||
{
|
||||
"invalid url",
|
||||
reqURL + badPath,
|
||||
true,
|
||||
"",
|
||||
func(bondId string) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqURL,
|
||||
false,
|
||||
"",
|
||||
func(bondId string) {
|
||||
// creating the record
|
||||
ets.createRecord(bondId)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun(ets.bondId)
|
||||
tc.url = fmt.Sprintf(reqURL, ets.bondId)
|
||||
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
require := ets.Require()
|
||||
if tc.expectErr {
|
||||
require.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryGetRecordsByBondIdResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
records := response.GetRecords()
|
||||
sr.NotZero(len(records))
|
||||
sr.Equal(records[0].GetBondId(), ets.bondId)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryGetRegistryModuleBalance() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/registry/v1/balance"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
preRun func(bondId string)
|
||||
}{
|
||||
{
|
||||
"invalid url",
|
||||
reqURL + badPath,
|
||||
true,
|
||||
"",
|
||||
func(bondId string) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"Success",
|
||||
reqURL,
|
||||
false,
|
||||
"",
|
||||
func(bondId string) {
|
||||
// creating the record
|
||||
ets.createRecord(bondId)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun(ets.bondId)
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
require := ets.Require()
|
||||
if tc.expectErr {
|
||||
require.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryGetRegistryModuleBalanceResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(response.GetBalances()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TestGRPCQueryNamesList() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
reqURL := val.APIAddress + "/cerc/registry/v1/names"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
errorMsg string
|
||||
preRun func(authorityName string)
|
||||
}{
|
||||
{
|
||||
"invalid url",
|
||||
reqURL + badPath,
|
||||
true,
|
||||
"",
|
||||
func(authorityName string) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
reqURL,
|
||||
false,
|
||||
"",
|
||||
func(authorityName string) {
|
||||
// create name record
|
||||
ets.createNameRecord(authorityName)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(tc.name, func() {
|
||||
tc.preRun("ListNameRecords")
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
ets.NoError(err)
|
||||
require := ets.Require()
|
||||
if tc.expectErr {
|
||||
require.Contains(string(resp), tc.errorMsg)
|
||||
} else {
|
||||
var response registrytypes.QueryNameRecordsResponse
|
||||
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &response)
|
||||
sr.NoError(err)
|
||||
sr.NotZero(len(response.GetNames()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,265 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
laconictestcli "git.vdb.to/cerc-io/laconicd/testutil/cli"
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
bondcli "git.vdb.to/cerc-io/laconicd/x/bond/client/cli"
|
||||
registrytypes "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
"git.vdb.to/cerc-io/laconicd/x/registry/client/cli"
|
||||
)
|
||||
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
|
||||
accountName string
|
||||
accountAddress string
|
||||
|
||||
bondId string
|
||||
}
|
||||
|
||||
func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
return &E2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) SetupSuite() {
|
||||
sr := ets.Require()
|
||||
ets.T().Log("setting up e2e test suite")
|
||||
|
||||
var err error
|
||||
|
||||
genesisState := ets.cfg.GenesisState
|
||||
var registryGenesis registrytypes.GenesisState
|
||||
ets.Require().NoError(ets.cfg.Codec.UnmarshalJSON(genesisState[registrytypes.ModuleName], ®istryGenesis))
|
||||
|
||||
ets.updateParams(®istryGenesis.Params)
|
||||
|
||||
registryGenesisBz, err := ets.cfg.Codec.MarshalJSON(®istryGenesis)
|
||||
ets.Require().NoError(err)
|
||||
genesisState[registrytypes.ModuleName] = registryGenesisBz
|
||||
ets.cfg.GenesisState = genesisState
|
||||
|
||||
ets.network, err = network.New(ets.T(), ets.T().TempDir(), ets.cfg)
|
||||
sr.NoError(err)
|
||||
|
||||
_, err = ets.network.WaitForHeight(2)
|
||||
sr.NoError(err)
|
||||
|
||||
// setting up random account
|
||||
ets.accountName = "accountName"
|
||||
ets.createAccountWithBalance(ets.accountName, &ets.accountAddress)
|
||||
|
||||
ets.bondId = ets.createBond()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) TearDownSuite() {
|
||||
ets.T().Log("tearing down e2e test suite")
|
||||
ets.network.Cleanup()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createAccountWithBalance(accountName string, accountAddress *string) {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||
sr.NoError(err)
|
||||
|
||||
newAddr, _ := info.GetAddress()
|
||||
out, err := clitestutil.MsgSendExec(
|
||||
val.ClientCtx,
|
||||
val.Address,
|
||||
newAddr,
|
||||
sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(100000000))),
|
||||
addresscodec.NewBech32Codec("laconic"),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(10))).String()),
|
||||
)
|
||||
sr.NoError(err)
|
||||
|
||||
var response sdk.TxResponse
|
||||
sr.NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, response.TxHash, 0))
|
||||
|
||||
*accountAddress = newAddr.String()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createBond() string {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
createBondCmd := bondcli.NewCreateBondCmd()
|
||||
args := []string{
|
||||
fmt.Sprintf("1000000%s", ets.cfg.BondDenom),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, createBondCmd, args)
|
||||
sr.NoError(err)
|
||||
var d sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, d.TxHash, 0))
|
||||
|
||||
// getting the bonds list and returning the bond-id
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := bondcli.GetQueryBondList()
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
}
|
||||
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
var queryResponse bondtypes.QueryBondsResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse)
|
||||
sr.NoError(err)
|
||||
|
||||
// extract bond id from bonds list
|
||||
bond := queryResponse.GetBonds()[0]
|
||||
return bond.GetId()
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) reserveName(authorityName string) {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := cli.GetCmdReserveAuthority()
|
||||
args := []string{
|
||||
authorityName,
|
||||
ets.accountAddress,
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
|
||||
var d sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, d.TxHash, 0))
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createNameRecord(authorityName string) {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
// reserving the name
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := cli.GetCmdReserveAuthority()
|
||||
args := []string{
|
||||
authorityName,
|
||||
ets.accountAddress,
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
var d sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, d.TxHash, 0))
|
||||
|
||||
// Get the bond-id
|
||||
bondId := ets.bondId
|
||||
|
||||
// adding bond-id to name authority
|
||||
args = []string{
|
||||
authorityName, bondId,
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
cmd = cli.GetCmdSetAuthorityBond()
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, d.TxHash, 0))
|
||||
|
||||
args = []string{
|
||||
fmt.Sprintf("lrn://%s/", authorityName),
|
||||
"test_hello_cid",
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
|
||||
cmd = cli.GetCmdSetName()
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, d.TxHash, 0))
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) createRecord(bondId string) {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
payloadPath := "../../data/examples/service_provider_example.yml"
|
||||
payloadFilePath, err := filepath.Abs(payloadPath)
|
||||
sr.NoError(err)
|
||||
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
}
|
||||
args = append([]string{payloadFilePath, bondId}, args...)
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := cli.GetCmdSetRecord()
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
sr.NoError(err)
|
||||
var d sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.NoError(laconictestcli.CheckTxCode(ets.network, val.ClientCtx, d.TxHash, 0))
|
||||
}
|
||||
|
||||
func (ets *E2ETestSuite) updateParams(params *registrytypes.Params) {
|
||||
params.RecordRent = sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(1000))
|
||||
params.RecordRentDuration = 10 * time.Second
|
||||
|
||||
params.AuthorityRent = sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(1000))
|
||||
params.AuthorityGracePeriod = 10 * time.Second
|
||||
|
||||
params.AuthorityAuctionCommitFee = sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(100))
|
||||
params.AuthorityAuctionRevealFee = sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(100))
|
||||
params.AuthorityAuctionMinimumBid = sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(500))
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/x/registry/client/cli"
|
||||
)
|
||||
|
||||
func (ets *E2ETestSuite) TestGetCmdSetRecord() {
|
||||
val := ets.network.Validators[0]
|
||||
sr := ets.Require()
|
||||
|
||||
bondId := ets.bondId
|
||||
payloadPath := "../../data/examples/service_provider_example.yml"
|
||||
payloadFilePath, err := filepath.Abs(payloadPath)
|
||||
sr.NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
"invalid request without bond id/without payload",
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
[]string{
|
||||
payloadFilePath, bondId,
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, ets.accountName),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", ets.cfg.BondDenom)),
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ets.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||
clientCtx := val.ClientCtx
|
||||
cmd := cli.GetCmdSetRecord()
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||
if tc.err {
|
||||
sr.Error(err)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
var d sdk.TxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &d)
|
||||
sr.NoError(err)
|
||||
sr.Zero(d.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
integrationTest "git.vdb.to/cerc-io/laconicd/tests/integration"
|
||||
types "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
)
|
||||
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
integrationTest.TestFixture
|
||||
|
||||
queryClient types.QueryClient
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) SetupTest() {
|
||||
err := kts.TestFixture.Setup()
|
||||
assert.Nil(kts.T(), err)
|
||||
|
||||
qr := kts.App.QueryHelper()
|
||||
kts.queryClient = types.NewQueryClient(qr)
|
||||
}
|
||||
|
||||
func TestAuctionKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
@ -1,359 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
integrationTest "git.vdb.to/cerc-io/laconicd/tests/integration"
|
||||
types "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
)
|
||||
|
||||
const testCommitHash = "71D8CF34026E32A3A34C2C2D4ADF25ABC8D7943A4619761BE27F196603D91B9D"
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryParams() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryParamsRequest
|
||||
}{
|
||||
{
|
||||
"fetch params",
|
||||
&types.QueryParamsRequest{},
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
resp, err := kts.queryClient.Params(context.Background(), test.req)
|
||||
kts.Require().Nil(err)
|
||||
kts.Require().Equal(*(resp.Params), types.DefaultParams())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetAuction() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetAuctionRequest
|
||||
createAuction bool
|
||||
}{
|
||||
{
|
||||
"fetch auction with empty auction ID",
|
||||
&types.QueryGetAuctionRequest{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fetch auction with valid auction ID",
|
||||
&types.QueryGetAuctionRequest{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
var expectedAuction types.Auction
|
||||
if test.createAuction {
|
||||
auction, _, err := kts.createAuctionAndCommitBid(false)
|
||||
kts.Require().Nil(err)
|
||||
test.req.Id = auction.Id
|
||||
expectedAuction = *auction
|
||||
}
|
||||
|
||||
resp, err := kts.queryClient.GetAuction(context.Background(), test.req)
|
||||
if test.createAuction {
|
||||
kts.Require().Nil(err)
|
||||
kts.Require().NotNil(resp.GetAuction())
|
||||
kts.Require().EqualExportedValues(expectedAuction, *(resp.GetAuction()))
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetAllAuctions() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryAuctionsRequest
|
||||
createAuctions bool
|
||||
auctionCount int
|
||||
}{
|
||||
{
|
||||
"fetch auctions when no auctions exist",
|
||||
&types.QueryAuctionsRequest{},
|
||||
false,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
"fetch auctions with one auction created",
|
||||
&types.QueryAuctionsRequest{},
|
||||
true,
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
if test.createAuctions {
|
||||
_, _, err := kts.createAuctionAndCommitBid(false)
|
||||
kts.Require().Nil(err)
|
||||
}
|
||||
|
||||
resp, _ := kts.queryClient.Auctions(context.Background(), test.req)
|
||||
kts.Require().Equal(test.auctionCount, len(resp.GetAuctions().Auctions))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetBids() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetBidsRequest
|
||||
createAuction bool
|
||||
commitBid bool
|
||||
bidCount int
|
||||
}{
|
||||
{
|
||||
"fetch all bids when no auction exists",
|
||||
&types.QueryGetBidsRequest{},
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"fetch all bids for valid auction but no added bids",
|
||||
&types.QueryGetBidsRequest{},
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"fetch all bids for valid auction and valid bid",
|
||||
&types.QueryGetBidsRequest{},
|
||||
true,
|
||||
true,
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
if test.createAuction {
|
||||
auction, _, err := kts.createAuctionAndCommitBid(test.commitBid)
|
||||
kts.Require().NoError(err)
|
||||
test.req.AuctionId = auction.Id
|
||||
}
|
||||
|
||||
resp, err := kts.queryClient.GetBids(context.Background(), test.req)
|
||||
if test.createAuction {
|
||||
kts.Require().Nil(err)
|
||||
kts.Require().Equal(test.bidCount, len(resp.GetBids()))
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetBid() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetBidRequest
|
||||
createAuctionAndBid bool
|
||||
}{
|
||||
{
|
||||
"fetch bid when bid does not exist",
|
||||
&types.QueryGetBidRequest{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fetch bid when valid bid exists",
|
||||
&types.QueryGetBidRequest{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
if test.createAuctionAndBid {
|
||||
auction, bid, err := kts.createAuctionAndCommitBid(test.createAuctionAndBid)
|
||||
kts.Require().NoError(err)
|
||||
test.req.AuctionId = auction.Id
|
||||
test.req.Bidder = bid.BidderAddress
|
||||
}
|
||||
|
||||
resp, err := kts.queryClient.GetBid(context.Background(), test.req)
|
||||
if test.createAuctionAndBid {
|
||||
kts.Require().NoError(err)
|
||||
kts.Require().NotNil(resp.Bid)
|
||||
kts.Require().Equal(test.req.Bidder, resp.Bid.BidderAddress)
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetAuctionsByBidder() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryAuctionsByBidderRequest
|
||||
createAuctionAndCommitBid bool
|
||||
auctionCount int
|
||||
}{
|
||||
{
|
||||
"get auctions by bidder with invalid bidder address",
|
||||
&types.QueryAuctionsByBidderRequest{},
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"get auctions by bidder with valid auction and bid",
|
||||
&types.QueryAuctionsByBidderRequest{},
|
||||
true,
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
if test.createAuctionAndCommitBid {
|
||||
_, bid, err := kts.createAuctionAndCommitBid(test.createAuctionAndCommitBid)
|
||||
kts.Require().NoError(err)
|
||||
test.req.BidderAddress = bid.BidderAddress
|
||||
}
|
||||
|
||||
resp, err := kts.queryClient.AuctionsByBidder(context.Background(), test.req)
|
||||
if test.createAuctionAndCommitBid {
|
||||
kts.Require().NoError(err)
|
||||
kts.Require().NotNil(resp.Auctions)
|
||||
kts.Require().Equal(test.auctionCount, len(resp.Auctions.Auctions))
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetAuctionsByOwner() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryAuctionsByOwnerRequest
|
||||
createAuction bool
|
||||
auctionCount int
|
||||
}{
|
||||
{
|
||||
"get auctions by owner with invalid owner address",
|
||||
&types.QueryAuctionsByOwnerRequest{},
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"get auctions by owner with valid auction",
|
||||
&types.QueryAuctionsByOwnerRequest{},
|
||||
true,
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
if test.createAuction {
|
||||
auction, _, err := kts.createAuctionAndCommitBid(false)
|
||||
kts.Require().NoError(err)
|
||||
test.req.OwnerAddress = auction.OwnerAddress
|
||||
}
|
||||
|
||||
resp, err := kts.queryClient.AuctionsByOwner(context.Background(), test.req)
|
||||
if test.createAuction {
|
||||
kts.Require().NoError(err)
|
||||
kts.Require().NotNil(resp.Auctions)
|
||||
kts.Require().Equal(test.auctionCount, len(resp.Auctions.Auctions))
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryBalance() {
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetAuctionModuleBalanceRequest
|
||||
createAuction bool
|
||||
auctionCount int
|
||||
}{
|
||||
{
|
||||
"get balance with no auctions created",
|
||||
&types.QueryGetAuctionModuleBalanceRequest{},
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"get balance with single auction created",
|
||||
&types.QueryGetAuctionModuleBalanceRequest{},
|
||||
true,
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
if test.createAuction {
|
||||
_, _, err := kts.createAuctionAndCommitBid(true)
|
||||
kts.Require().NoError(err)
|
||||
}
|
||||
|
||||
resp, err := kts.queryClient.GetAuctionModuleBalance(context.Background(), test.req)
|
||||
kts.Require().NoError(err)
|
||||
kts.Require().Equal(test.auctionCount, len(resp.GetBalance()))
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) createAuctionAndCommitBid(commitBid bool) (*types.Auction, *types.Bid, error) {
|
||||
ctx, k := kts.SdkCtx, kts.AuctionKeeper
|
||||
accCount := 1
|
||||
if commitBid {
|
||||
accCount++
|
||||
}
|
||||
|
||||
// Create funded account(s)
|
||||
accounts := simtestutil.AddTestAddrs(kts.BankKeeper, integrationTest.BondDenomProvider{}, ctx, accCount, math.NewInt(1000000))
|
||||
|
||||
auction, err := k.CreateAuction(
|
||||
ctx,
|
||||
types.MsgCreateAuction{
|
||||
Kind: types.AuctionKindVickrey,
|
||||
Signer: accounts[0].String(),
|
||||
CommitsDuration: 5 * time.Minute,
|
||||
RevealsDuration: 5 * time.Minute,
|
||||
CommitFee: sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(1000)),
|
||||
RevealFee: sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(1000)),
|
||||
MinimumBid: sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(1000000)),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if commitBid {
|
||||
bid, err := k.CommitBid(ctx, types.NewMsgCommitBid(auction.Id, testCommitHash, accounts[1]))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return auction, bid, nil
|
||||
}
|
||||
|
||||
return auction, nil, nil
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
integrationTest "git.vdb.to/cerc-io/laconicd/tests/integration"
|
||||
types "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
)
|
||||
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
integrationTest.TestFixture
|
||||
|
||||
queryClient types.QueryClient
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) SetupTest() {
|
||||
err := kts.TestFixture.Setup()
|
||||
assert.Nil(kts.T(), err)
|
||||
|
||||
qr := kts.App.QueryHelper()
|
||||
kts.queryClient = types.NewQueryClient(qr)
|
||||
}
|
||||
|
||||
func TestBondKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
@ -1,210 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
integrationTest "git.vdb.to/cerc-io/laconicd/tests/integration"
|
||||
types "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
)
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryParams() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryParamsRequest
|
||||
}{
|
||||
{
|
||||
"fetch params",
|
||||
&types.QueryParamsRequest{},
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||
resp, err := kts.queryClient.Params(context.Background(), test.req)
|
||||
kts.Require().Nil(err)
|
||||
kts.Require().Equal(*(resp.Params), types.DefaultParams())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryBondsList() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryBondsRequest
|
||||
resp *types.QueryBondsResponse
|
||||
noOfBonds int
|
||||
createBonds bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
&types.QueryBondsRequest{},
|
||||
&types.QueryBondsResponse{},
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Get Bonds",
|
||||
&types.QueryBondsRequest{},
|
||||
&types.QueryBondsResponse{},
|
||||
1,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
if test.createBonds {
|
||||
_, err := kts.createBond()
|
||||
kts.Require().NoError(err)
|
||||
}
|
||||
resp, _ := kts.queryClient.Bonds(context.Background(), test.req)
|
||||
kts.Require().Equal(test.noOfBonds, len(resp.GetBonds()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryBondByBondId() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetBondByIdRequest
|
||||
createBonds bool
|
||||
errResponse bool
|
||||
bondId string
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
&types.QueryGetBondByIdRequest{},
|
||||
false,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"Get Bond By ID",
|
||||
&types.QueryGetBondByIdRequest{},
|
||||
true,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
if test.createBonds {
|
||||
bond, err := kts.createBond()
|
||||
kts.Require().NoError(err)
|
||||
test.req.Id = bond.Id
|
||||
}
|
||||
resp, err := kts.queryClient.GetBondById(context.Background(), test.req)
|
||||
if !test.errResponse {
|
||||
kts.Require().Nil(err)
|
||||
kts.Require().NotNil(resp.GetBond())
|
||||
kts.Require().Equal(test.req.Id, resp.GetBond().GetId())
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetBondsByOwner() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetBondsByOwnerRequest
|
||||
noOfBonds int
|
||||
createBonds bool
|
||||
errResponse bool
|
||||
bondId string
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
&types.QueryGetBondsByOwnerRequest{},
|
||||
0,
|
||||
false,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"Get Bond By Owner",
|
||||
&types.QueryGetBondsByOwnerRequest{},
|
||||
1,
|
||||
true,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
if test.createBonds {
|
||||
bond, err := kts.createBond()
|
||||
kts.Require().NoError(err)
|
||||
test.req.Owner = bond.Owner
|
||||
}
|
||||
resp, err := kts.queryClient.GetBondsByOwner(context.Background(), test.req)
|
||||
if !test.errResponse {
|
||||
kts.Require().Nil(err)
|
||||
kts.Require().NotNil(resp.GetBonds())
|
||||
kts.Require().Equal(test.noOfBonds, len(resp.GetBonds()))
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetModuleBalance() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetBondModuleBalanceRequest
|
||||
noOfBonds int
|
||||
createBonds bool
|
||||
errResponse bool
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
&types.QueryGetBondModuleBalanceRequest{},
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
if test.createBonds {
|
||||
_, err := kts.createBond()
|
||||
kts.Require().NoError(err)
|
||||
}
|
||||
resp, err := kts.queryClient.GetBondModuleBalance(context.Background(), test.req)
|
||||
if !test.errResponse {
|
||||
kts.Require().Nil(err)
|
||||
kts.Require().NotNil(resp.GetBalance())
|
||||
kts.Require().Equal(resp.GetBalance(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10))))
|
||||
} else {
|
||||
kts.Require().NotNil(err)
|
||||
kts.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) createBond() (*types.Bond, error) {
|
||||
ctx, k := kts.SdkCtx, kts.BondKeeper
|
||||
accCount := 1
|
||||
|
||||
// Create funded account(s)
|
||||
accounts := simtestutil.AddTestAddrs(kts.BankKeeper, integrationTest.BondDenomProvider{}, ctx, accCount, math.NewInt(1000))
|
||||
|
||||
bond, err := k.CreateBond(ctx, accounts[0], sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10))))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bond, nil
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
package integration_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
cmtprototypes "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/integration"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
|
||||
auctionTypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
auctionkeeper "git.vdb.to/cerc-io/laconicd/x/auction/keeper"
|
||||
auctionmodule "git.vdb.to/cerc-io/laconicd/x/auction/module"
|
||||
bondTypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
bondkeeper "git.vdb.to/cerc-io/laconicd/x/bond/keeper"
|
||||
bondmodule "git.vdb.to/cerc-io/laconicd/x/bond/module"
|
||||
registryTypes "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
registrykeeper "git.vdb.to/cerc-io/laconicd/x/registry/keeper"
|
||||
registrymodule "git.vdb.to/cerc-io/laconicd/x/registry/module"
|
||||
)
|
||||
|
||||
type TestFixture struct {
|
||||
App *integration.App
|
||||
|
||||
SdkCtx sdk.Context
|
||||
cdc codec.Codec
|
||||
keys map[string]*storetypes.KVStoreKey
|
||||
|
||||
AccountKeeper authkeeper.AccountKeeper
|
||||
BankKeeper bankkeeper.Keeper
|
||||
|
||||
AuctionKeeper *auctionkeeper.Keeper
|
||||
BondKeeper *bondkeeper.Keeper
|
||||
RegistryKeeper registrykeeper.Keeper
|
||||
}
|
||||
|
||||
func (tf *TestFixture) Setup() error {
|
||||
keys := storetypes.NewKVStoreKeys(
|
||||
authtypes.StoreKey, banktypes.StoreKey, auctionTypes.StoreKey, bondTypes.StoreKey, registryTypes.StoreKey,
|
||||
)
|
||||
cdc := moduletestutil.MakeTestEncodingConfig(
|
||||
auth.AppModuleBasic{},
|
||||
auctionmodule.AppModule{},
|
||||
bondmodule.AppModule{},
|
||||
registrymodule.AppModule{},
|
||||
).Codec
|
||||
|
||||
logger := log.NewNopLogger() // Use log.NewTestLogger(kts.T()) for help with debugging
|
||||
cms := integration.CreateMultiStore(keys, logger)
|
||||
|
||||
newCtx := sdk.NewContext(cms, cmtprototypes.Header{}, true, logger)
|
||||
|
||||
authority := authtypes.NewModuleAddress("gov")
|
||||
|
||||
maccPerms := map[string][]string{
|
||||
minttypes.ModuleName: {authtypes.Minter},
|
||||
auctionTypes.ModuleName: {},
|
||||
auctionTypes.AuctionBurnModuleAccountName: {},
|
||||
bondTypes.ModuleName: {},
|
||||
registryTypes.ModuleName: {},
|
||||
registryTypes.RecordRentModuleAccountName: {},
|
||||
registryTypes.AuthorityRentModuleAccountName: {},
|
||||
}
|
||||
|
||||
accountKeeper := authkeeper.NewAccountKeeper(
|
||||
cdc,
|
||||
runtime.NewKVStoreService(keys[authtypes.StoreKey]),
|
||||
authtypes.ProtoBaseAccount,
|
||||
maccPerms,
|
||||
addresscodec.NewBech32Codec(sdk.Bech32MainPrefix),
|
||||
sdk.Bech32MainPrefix,
|
||||
authority.String(),
|
||||
)
|
||||
|
||||
blockedAddresses := map[string]bool{
|
||||
accountKeeper.GetAuthority(): false,
|
||||
}
|
||||
bankKeeper := bankkeeper.NewBaseKeeper(
|
||||
cdc,
|
||||
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
|
||||
accountKeeper,
|
||||
blockedAddresses,
|
||||
authority.String(),
|
||||
log.NewNopLogger(),
|
||||
)
|
||||
|
||||
auctionKeeper := auctionkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[auctionTypes.StoreKey]), accountKeeper, bankKeeper, authority.String())
|
||||
|
||||
bondKeeper := bondkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[bondTypes.StoreKey]), accountKeeper, bankKeeper, authority.String())
|
||||
|
||||
registryKeeper := registrykeeper.NewKeeper(
|
||||
cdc,
|
||||
runtime.NewKVStoreService(keys[registryTypes.StoreKey]),
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
bondKeeper,
|
||||
auctionKeeper,
|
||||
authority.String(),
|
||||
)
|
||||
|
||||
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
|
||||
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
|
||||
auctionModule := auctionmodule.NewAppModule(cdc, auctionKeeper)
|
||||
bondModule := bondmodule.NewAppModule(cdc, bondKeeper)
|
||||
registryModule := registrymodule.NewAppModule(cdc, registryKeeper)
|
||||
|
||||
integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{
|
||||
authtypes.ModuleName: authModule,
|
||||
banktypes.ModuleName: bankModule,
|
||||
auctionTypes.ModuleName: auctionModule,
|
||||
bondTypes.ModuleName: bondModule,
|
||||
registryTypes.ModuleName: registryModule,
|
||||
})
|
||||
|
||||
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
|
||||
|
||||
// Register MsgServer and QueryServer
|
||||
auctionTypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), auctionkeeper.NewMsgServerImpl(auctionKeeper))
|
||||
auctionTypes.RegisterQueryServer(integrationApp.QueryHelper(), auctionkeeper.NewQueryServerImpl(auctionKeeper))
|
||||
|
||||
bondTypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), bondkeeper.NewMsgServerImpl(bondKeeper))
|
||||
bondTypes.RegisterQueryServer(integrationApp.QueryHelper(), bondkeeper.NewQueryServerImpl(bondKeeper))
|
||||
|
||||
registryTypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), registrykeeper.NewMsgServerImpl(registryKeeper))
|
||||
registryTypes.RegisterQueryServer(integrationApp.QueryHelper(), registrykeeper.NewQueryServerImpl(registryKeeper))
|
||||
|
||||
// set default params
|
||||
if err := auctionKeeper.Params.Set(sdkCtx, auctionTypes.DefaultParams()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bondKeeper.Params.Set(sdkCtx, bondTypes.DefaultParams()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := registryKeeper.Params.Set(sdkCtx, registryTypes.DefaultParams()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tf.App = integrationApp
|
||||
tf.SdkCtx, tf.cdc, tf.keys = sdkCtx, cdc, keys
|
||||
tf.AccountKeeper, tf.BankKeeper = accountKeeper, bankKeeper
|
||||
tf.AuctionKeeper, tf.BondKeeper, tf.RegistryKeeper = auctionKeeper, bondKeeper, registryKeeper
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type BondDenomProvider struct{}
|
||||
|
||||
func (bdp BondDenomProvider) BondDenom(ctx context.Context) (string, error) {
|
||||
return sdk.DefaultBondDenom, nil
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
integrationTest "git.vdb.to/cerc-io/laconicd/tests/integration"
|
||||
bondTypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
types "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
)
|
||||
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
integrationTest.TestFixture
|
||||
|
||||
queryClient types.QueryClient
|
||||
|
||||
accounts []sdk.AccAddress
|
||||
bond bondTypes.Bond
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) SetupTest() {
|
||||
err := kts.TestFixture.Setup()
|
||||
assert.Nil(kts.T(), err)
|
||||
|
||||
// set default params
|
||||
err = kts.RegistryKeeper.Params.Set(kts.SdkCtx, types.DefaultParams())
|
||||
assert.Nil(kts.T(), err)
|
||||
|
||||
qr := kts.App.QueryHelper()
|
||||
kts.queryClient = types.NewQueryClient(qr)
|
||||
|
||||
// Create a bond
|
||||
bond, err := kts.createBond()
|
||||
assert.Nil(kts.T(), err)
|
||||
kts.bond = *bond
|
||||
}
|
||||
|
||||
func TestRegistryKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) createBond() (*bondTypes.Bond, error) {
|
||||
ctx := kts.SdkCtx
|
||||
|
||||
// Create a funded account
|
||||
kts.accounts = simtestutil.AddTestAddrs(kts.BankKeeper, integrationTest.BondDenomProvider{}, ctx, 1, math.NewInt(1000000000000))
|
||||
|
||||
bond, err := kts.BondKeeper.CreateBond(ctx, kts.accounts[0], sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(1000000000))))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bond, nil
|
||||
}
|
||||
@ -1,421 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
types "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
"git.vdb.to/cerc-io/laconicd/x/registry/client/cli"
|
||||
"git.vdb.to/cerc-io/laconicd/x/registry/helpers"
|
||||
registryKeeper "git.vdb.to/cerc-io/laconicd/x/registry/keeper"
|
||||
)
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryParams() {
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryParamsRequest
|
||||
}{
|
||||
{
|
||||
"Get Params",
|
||||
&types.QueryParamsRequest{},
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
resp, _ := kts.queryClient.Params(context.Background(), test.req)
|
||||
defaultParams := types.DefaultParams()
|
||||
kts.Require().Equal(defaultParams.String(), resp.GetParams().String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcGetRecordLists() {
|
||||
ctx, queryClient := kts.SdkCtx, kts.queryClient
|
||||
sr := kts.Require()
|
||||
|
||||
var recordId string
|
||||
examples := []string{
|
||||
"../../../data/examples/service_provider_example.yml",
|
||||
"../../../data/examples/website_registration_example.yml",
|
||||
"../../../data/examples/general_record_example.yml",
|
||||
}
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryRecordsRequest
|
||||
createRecords bool
|
||||
expErr bool
|
||||
noOfRecords int
|
||||
}{
|
||||
{
|
||||
"Empty Records",
|
||||
&types.QueryRecordsRequest{},
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"List Records",
|
||||
&types.QueryRecordsRequest{},
|
||||
true,
|
||||
false,
|
||||
3,
|
||||
},
|
||||
{
|
||||
"Filter with type",
|
||||
&types.QueryRecordsRequest{
|
||||
Attributes: []*types.QueryRecordsRequest_KeyValueInput{
|
||||
{
|
||||
Key: "type",
|
||||
Value: &types.QueryRecordsRequest_ValueInput{
|
||||
Value: &types.QueryRecordsRequest_ValueInput_String_{String_: "WebsiteRegistrationRecord"},
|
||||
},
|
||||
},
|
||||
},
|
||||
All: true,
|
||||
},
|
||||
true,
|
||||
false,
|
||||
1,
|
||||
},
|
||||
// Skip the following test as querying with recursive values not supported (PR https://git.vdb.to/cerc-io/laconicd/pulls/112)
|
||||
// See function RecordsFromAttributes (QueryValueToJSON call) in the registry keeper implementation (x/registry/keeper/keeper.go)
|
||||
// {
|
||||
// "Filter with tag (extant) (https://git.vdb.to/cerc-io/laconicd/issues/129)",
|
||||
// &types.QueryRecordsRequest{
|
||||
// Attributes: []*types.QueryRecordsRequest_KeyValueInput{
|
||||
// {
|
||||
// Key: "tags",
|
||||
// // Value: &types.QueryRecordsRequest_ValueInput{
|
||||
// // Value: &types.QueryRecordsRequest_ValueInput_String_{"tagA"},
|
||||
// // },
|
||||
// Value: &types.QueryRecordsRequest_ValueInput{
|
||||
// Value: &types.QueryRecordsRequest_ValueInput_Array{Array: &types.QueryRecordsRequest_ArrayInput{
|
||||
// Values: []*types.QueryRecordsRequest_ValueInput{
|
||||
// {
|
||||
// Value: &types.QueryRecordsRequest_ValueInput_String_{"tagA"},
|
||||
// },
|
||||
// },
|
||||
// }},
|
||||
// },
|
||||
// // Throws: "Recursive query values are not supported"
|
||||
// },
|
||||
// },
|
||||
// All: true,
|
||||
// },
|
||||
// true,
|
||||
// false,
|
||||
// 1,
|
||||
// },
|
||||
{
|
||||
"Filter with tag (non-existent) (https://git.vdb.to/cerc-io/laconicd/issues/129)",
|
||||
&types.QueryRecordsRequest{
|
||||
Attributes: []*types.QueryRecordsRequest_KeyValueInput{
|
||||
{
|
||||
Key: "tags",
|
||||
Value: &types.QueryRecordsRequest_ValueInput{
|
||||
Value: &types.QueryRecordsRequest_ValueInput_String_{String_: "NOEXIST"},
|
||||
},
|
||||
},
|
||||
},
|
||||
All: true,
|
||||
},
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"Filter test for key collision (https://git.vdb.to/cerc-io/laconicd/issues/122)",
|
||||
&types.QueryRecordsRequest{
|
||||
Attributes: []*types.QueryRecordsRequest_KeyValueInput{
|
||||
{
|
||||
Key: "typ",
|
||||
Value: &types.QueryRecordsRequest_ValueInput{
|
||||
Value: &types.QueryRecordsRequest_ValueInput_String_{String_: "eWebsiteRegistrationRecord"},
|
||||
},
|
||||
},
|
||||
},
|
||||
All: true,
|
||||
},
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"Filter with attributes ServiceProviderRegistration",
|
||||
&types.QueryRecordsRequest{
|
||||
Attributes: []*types.QueryRecordsRequest_KeyValueInput{
|
||||
{
|
||||
Key: "x500state_name",
|
||||
Value: &types.QueryRecordsRequest_ValueInput{
|
||||
Value: &types.QueryRecordsRequest_ValueInput_String_{String_: "california"},
|
||||
},
|
||||
},
|
||||
},
|
||||
All: true,
|
||||
},
|
||||
true,
|
||||
false,
|
||||
1,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
if test.createRecords {
|
||||
for _, example := range examples {
|
||||
filePath, err := filepath.Abs(example)
|
||||
sr.NoError(err)
|
||||
payloadType, err := cli.GetPayloadFromFile(filePath)
|
||||
sr.NoError(err)
|
||||
payload := payloadType.ToPayload()
|
||||
record, err := kts.RegistryKeeper.SetRecord(ctx, types.MsgSetRecord{
|
||||
BondId: kts.bond.GetId(),
|
||||
Signer: kts.accounts[0].String(),
|
||||
Payload: payload,
|
||||
})
|
||||
sr.NoError(err)
|
||||
sr.NotNil(record.Id)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := queryClient.Records(context.Background(), test.req)
|
||||
|
||||
if test.expErr {
|
||||
kts.Error(err)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
sr.Equal(test.noOfRecords, len(resp.GetRecords()))
|
||||
if test.createRecords && test.noOfRecords > 0 {
|
||||
recordId = resp.GetRecords()[0].GetId()
|
||||
sr.NotZero(resp.GetRecords())
|
||||
sr.Equal(resp.GetRecords()[0].GetBondId(), kts.bond.GetId())
|
||||
|
||||
for _, record := range resp.GetRecords() {
|
||||
recAttr := helpers.MustUnmarshalJSON[types.AttributeMap](record.Attributes)
|
||||
|
||||
for _, attr := range test.req.GetAttributes() {
|
||||
enc, err := registryKeeper.QueryValueToJSON(attr.Value)
|
||||
sr.NoError(err)
|
||||
av := helpers.MustUnmarshalJSON[any](enc)
|
||||
|
||||
if nil != av && nil != recAttr[attr.Key] &&
|
||||
reflect.Slice == reflect.TypeOf(recAttr[attr.Key]).Kind() &&
|
||||
reflect.Slice != reflect.TypeOf(av).Kind() {
|
||||
found := false
|
||||
allValues := recAttr[attr.Key].([]interface{})
|
||||
for i := range allValues {
|
||||
if av == allValues[i] {
|
||||
fmt.Printf("Found %s in %s", allValues[i], recAttr[attr.Key])
|
||||
found = true
|
||||
}
|
||||
}
|
||||
sr.Equal(true, found, fmt.Sprintf("Unable to find %s in %s", av, recAttr[attr.Key]))
|
||||
} else {
|
||||
if attr.Key[:4] == "x500" {
|
||||
sr.Equal(av, recAttr["x500"].(map[string]interface{})[attr.Key[4:]])
|
||||
} else {
|
||||
sr.Equal(av, recAttr[attr.Key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Get the records by record id
|
||||
testCases1 := []struct {
|
||||
msg string
|
||||
req *types.QueryGetRecordRequest
|
||||
createRecord bool
|
||||
expErr bool
|
||||
noOfRecords int
|
||||
}{
|
||||
{
|
||||
"Invalid Request without record id",
|
||||
&types.QueryGetRecordRequest{},
|
||||
false,
|
||||
true,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"With Record ID",
|
||||
&types.QueryGetRecordRequest{
|
||||
Id: recordId,
|
||||
},
|
||||
true,
|
||||
false,
|
||||
1,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases1 {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
resp, err := queryClient.GetRecord(context.Background(), test.req)
|
||||
|
||||
if test.expErr {
|
||||
kts.Error(err)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
sr.NotNil(resp.GetRecord())
|
||||
if test.createRecord {
|
||||
sr.Equal(resp.GetRecord().BondId, kts.bond.GetId())
|
||||
sr.Equal(resp.GetRecord().Id, recordId)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Get the records by record id
|
||||
testCasesByBondId := []struct {
|
||||
msg string
|
||||
req *types.QueryGetRecordsByBondIdRequest
|
||||
createRecord bool
|
||||
expErr bool
|
||||
noOfRecords int
|
||||
}{
|
||||
{
|
||||
"Invalid Request without bond id",
|
||||
&types.QueryGetRecordsByBondIdRequest{},
|
||||
false,
|
||||
true,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"With Bond ID",
|
||||
&types.QueryGetRecordsByBondIdRequest{
|
||||
Id: kts.bond.GetId(),
|
||||
},
|
||||
true,
|
||||
false,
|
||||
1,
|
||||
},
|
||||
}
|
||||
for _, test := range testCasesByBondId {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
resp, err := queryClient.GetRecordsByBondId(context.Background(), test.req)
|
||||
|
||||
if test.expErr {
|
||||
sr.Zero(resp.GetRecords())
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
sr.NotNil(resp.GetRecords())
|
||||
if test.createRecord {
|
||||
sr.NotZero(resp.GetRecords())
|
||||
sr.Equal(resp.GetRecords()[0].GetBondId(), kts.bond.GetId())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryRegistryModuleBalance() {
|
||||
queryClient, ctx := kts.queryClient, kts.SdkCtx
|
||||
sr := kts.Require()
|
||||
examples := []string{
|
||||
"../../../data/examples/service_provider_example.yml",
|
||||
"../../../data/examples/website_registration_example.yml",
|
||||
}
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryGetRegistryModuleBalanceRequest
|
||||
createRecords bool
|
||||
expErr bool
|
||||
noOfRecords int
|
||||
}{
|
||||
{
|
||||
"Get Module Balance",
|
||||
&types.QueryGetRegistryModuleBalanceRequest{},
|
||||
true,
|
||||
false,
|
||||
1,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
if test.createRecords {
|
||||
for _, example := range examples {
|
||||
filePath, err := filepath.Abs(example)
|
||||
sr.NoError(err)
|
||||
payloadType, err := cli.GetPayloadFromFile(filePath)
|
||||
sr.NoError(err)
|
||||
payload := payloadType.ToPayload()
|
||||
record, err := kts.RegistryKeeper.SetRecord(ctx, types.MsgSetRecord{
|
||||
BondId: kts.bond.GetId(),
|
||||
Signer: kts.accounts[0].String(),
|
||||
Payload: payload,
|
||||
})
|
||||
sr.NoError(err)
|
||||
sr.NotNil(record.Id)
|
||||
}
|
||||
}
|
||||
resp, err := queryClient.GetRegistryModuleBalance(context.Background(), test.req)
|
||||
if test.expErr {
|
||||
kts.Error(err)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
sr.Equal(test.noOfRecords, len(resp.GetBalances()))
|
||||
if test.createRecords {
|
||||
balance := resp.GetBalances()[0]
|
||||
sr.Equal(balance.AccountName, types.RecordRentModuleAccountName)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (kts *KeeperTestSuite) TestGrpcQueryWhoIs() {
|
||||
queryClient, ctx := kts.queryClient, kts.SdkCtx
|
||||
sr := kts.Require()
|
||||
authorityName := "TestGrpcQueryWhoIs"
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
req *types.QueryWhoisRequest
|
||||
createName bool
|
||||
expErr bool
|
||||
noOfRecords int
|
||||
}{
|
||||
{
|
||||
"Invalid Request without name",
|
||||
&types.QueryWhoisRequest{},
|
||||
false,
|
||||
true,
|
||||
1,
|
||||
},
|
||||
{
|
||||
"Success",
|
||||
&types.QueryWhoisRequest{},
|
||||
true,
|
||||
false,
|
||||
1,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
kts.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||
if test.createName {
|
||||
err := kts.RegistryKeeper.ReserveAuthority(ctx, types.MsgReserveAuthority{
|
||||
Name: authorityName,
|
||||
Signer: kts.accounts[0].String(),
|
||||
Owner: kts.accounts[0].String(),
|
||||
})
|
||||
sr.NoError(err)
|
||||
test.req = &types.QueryWhoisRequest{Name: authorityName}
|
||||
}
|
||||
resp, err := queryClient.Whois(context.Background(), test.req)
|
||||
if test.expErr {
|
||||
kts.Error(err)
|
||||
sr.Nil(resp)
|
||||
} else {
|
||||
sr.NoError(err)
|
||||
if test.createName {
|
||||
nameAuth := resp.NameAuthority
|
||||
sr.NotNil(nameAuth)
|
||||
sr.Equal(nameAuth.OwnerAddress, kts.accounts[0].String())
|
||||
sr.Equal(types.AuthorityActive, nameAuth.Status)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
28
tests/system/cli.go
Normal file
28
tests/system/cli.go
Normal file
@ -0,0 +1,28 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"cosmossdk.io/systemtests"
|
||||
)
|
||||
|
||||
func NewCLIWrapper(t *testing.T, sut *SystemUnderTest, verbose bool, fees string) *systemtests.CLIWrapper {
|
||||
t.Helper()
|
||||
return systemtests.NewCLIWrapperX(
|
||||
t,
|
||||
sut.execBinary,
|
||||
sut.rpcAddr,
|
||||
sut.chainID,
|
||||
sut.AwaitNextBlock,
|
||||
sut.nodesCount,
|
||||
filepath.Join(WorkDir, sut.outputDir),
|
||||
fees,
|
||||
verbose,
|
||||
assert.NoError,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
}
|
||||
151
tests/system/events.go
Normal file
151
tests/system/events.go
Normal file
@ -0,0 +1,151 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cometbft/cometbft/libs/sync"
|
||||
client "github.com/cometbft/cometbft/rpc/client/http"
|
||||
ctypes "github.com/cometbft/cometbft/rpc/core/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// EventListener watches for events on the chain
|
||||
type EventListener struct {
|
||||
t *testing.T
|
||||
client *client.HTTP
|
||||
}
|
||||
|
||||
var DefaultWaitTime = 30 * time.Second
|
||||
|
||||
type (
|
||||
CleanupFn func()
|
||||
EventConsumer func(e ctypes.ResultEvent) (more bool)
|
||||
)
|
||||
|
||||
// NewEventListener event listener
|
||||
func NewEventListener(t *testing.T, rpcAddr string) *EventListener {
|
||||
t.Helper()
|
||||
httpClient, err := client.New(rpcAddr)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, httpClient.Start())
|
||||
return &EventListener{client: httpClient, t: t}
|
||||
}
|
||||
|
||||
// Subscribe to receive events for a topic. Does not block.
|
||||
// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events
|
||||
func (l *EventListener) Subscribe(query string, cb EventConsumer) func() {
|
||||
ctx, done := context.WithCancel(context.Background())
|
||||
l.t.Cleanup(done)
|
||||
eventsChan, err := l.client.WSEvents.Subscribe(ctx, "testing", query)
|
||||
require.NoError(l.t, err)
|
||||
cleanup := func() {
|
||||
ctx, _ := context.WithTimeout(ctx, DefaultWaitTime) //nolint:govet // used in cleanup only
|
||||
go l.client.WSEvents.Unsubscribe(ctx, "testing", query) //nolint:errcheck // used by tests only
|
||||
done()
|
||||
}
|
||||
go func() {
|
||||
for e := range eventsChan {
|
||||
if !cb(e) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return cleanup
|
||||
}
|
||||
|
||||
// AwaitQuery blocks and waits for a single result or timeout. This can be used with `broadcast-mode=async`.
|
||||
// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events
|
||||
func (l *EventListener) AwaitQuery(query string, optMaxWaitTime ...time.Duration) *ctypes.ResultEvent {
|
||||
c, result := CaptureSingleEventConsumer()
|
||||
maxWaitTime := DefaultWaitTime
|
||||
if len(optMaxWaitTime) != 0 {
|
||||
maxWaitTime = optMaxWaitTime[0]
|
||||
}
|
||||
cleanupFn := l.Subscribe(query, TimeoutConsumer(l.t, maxWaitTime, c))
|
||||
l.t.Cleanup(cleanupFn)
|
||||
return result
|
||||
}
|
||||
|
||||
// TimeoutConsumer is an event consumer decorator with a max wait time. Panics when wait time exceeded without
|
||||
// a result returned
|
||||
func TimeoutConsumer(t *testing.T, maxWaitTime time.Duration, next EventConsumer) EventConsumer {
|
||||
t.Helper()
|
||||
ctx, done := context.WithCancel(context.Background())
|
||||
t.Cleanup(done)
|
||||
timeout := time.NewTimer(maxWaitTime)
|
||||
timedOut := make(chan struct{}, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-timeout.C:
|
||||
timedOut <- struct{}{}
|
||||
close(timedOut)
|
||||
}
|
||||
}()
|
||||
return func(e ctypes.ResultEvent) (more bool) {
|
||||
select {
|
||||
case <-timedOut:
|
||||
t.Fatalf("Timeout waiting for new events %s", maxWaitTime)
|
||||
return false
|
||||
default:
|
||||
timeout.Reset(maxWaitTime)
|
||||
result := next(e)
|
||||
if !result {
|
||||
done()
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CaptureSingleEventConsumer consumes one event. No timeout
|
||||
func CaptureSingleEventConsumer() (EventConsumer, *ctypes.ResultEvent) {
|
||||
var result ctypes.ResultEvent
|
||||
return func(e ctypes.ResultEvent) (more bool) {
|
||||
return false
|
||||
}, &result
|
||||
}
|
||||
|
||||
// CaptureAllEventsConsumer is an `EventConsumer` that captures all events until `done()` is called to stop or timeout happens.
|
||||
// The consumer works async in the background and returns all the captured events when `done()` is called.
|
||||
// This can be used to verify that certain events have happened.
|
||||
// Example usage:
|
||||
//
|
||||
// c, done := CaptureAllEventsConsumer(t)
|
||||
// query := `tm.event='Tx'`
|
||||
// cleanupFn := l.Subscribe(query, c)
|
||||
// t.Cleanup(cleanupFn)
|
||||
//
|
||||
// // do something in your test that create events
|
||||
//
|
||||
// assert.Len(t, done(), 1) // then verify your assumption
|
||||
func CaptureAllEventsConsumer(t *testing.T, optMaxWaitTime ...time.Duration) (c EventConsumer, done func() []ctypes.ResultEvent) {
|
||||
t.Helper()
|
||||
maxWaitTime := DefaultWaitTime
|
||||
if len(optMaxWaitTime) != 0 {
|
||||
maxWaitTime = optMaxWaitTime[0]
|
||||
}
|
||||
var (
|
||||
mu sync.Mutex
|
||||
capturedEvents []ctypes.ResultEvent
|
||||
exit bool
|
||||
)
|
||||
collectEventsConsumer := func(e ctypes.ResultEvent) (more bool) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if exit {
|
||||
return false
|
||||
}
|
||||
capturedEvents = append(capturedEvents, e)
|
||||
return true
|
||||
}
|
||||
|
||||
return TimeoutConsumer(t, maxWaitTime, collectEventsConsumer), func() []ctypes.ResultEvent {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
exit = true
|
||||
return capturedEvents
|
||||
}
|
||||
}
|
||||
7
tests/system/main_test.go
Normal file
7
tests/system/main_test.go
Normal file
@ -0,0 +1,7 @@
|
||||
package system
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
RunTests(m)
|
||||
}
|
||||
253
tests/system/registry_test.go
Normal file
253
tests/system/registry_test.go
Normal file
@ -0,0 +1,253 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/systemtests"
|
||||
accountstypes "cosmossdk.io/x/accounts/v1"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
"git.vdb.to/cerc-io/laconicd/x/nitrobank"
|
||||
registrytypes "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
)
|
||||
|
||||
var recordFilePath = "../data/examples/service_provider_example.yml"
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
if recordFilePath, err = filepath.Abs(recordFilePath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if _, err = os.Stat(recordFilePath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type systemTestSuite struct {
|
||||
t *testing.T
|
||||
fees string
|
||||
}
|
||||
|
||||
type registryTestSuite struct {
|
||||
*systemTestSuite
|
||||
|
||||
accountName string
|
||||
accountAddress string
|
||||
bondDenom string
|
||||
bondId string
|
||||
}
|
||||
|
||||
func newSystemTestSuite(t *testing.T, fees string) *systemTestSuite {
|
||||
return &systemTestSuite{
|
||||
t: t,
|
||||
fees: fees,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *systemTestSuite) cli() *systemtests.CLIWrapper {
|
||||
return NewCLIWrapper(s.t, sut, verbose, s.fees)
|
||||
}
|
||||
|
||||
func (s *systemTestSuite) SubTest(name string, f func(t *systemTestSuite)) {
|
||||
s.t.Run(name, func(t *testing.T) {
|
||||
subsuite := newSystemTestSuite(t, s.fees)
|
||||
f(subsuite)
|
||||
})
|
||||
}
|
||||
|
||||
// run manually:
|
||||
// go test ./tests/system -test.v -timeout 10m --verbose --nodes-count 1 -run TestRegistrySetRecord
|
||||
func TestRegistrySetRecord(t *testing.T) {
|
||||
s := setupSuite(t)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
"request with invalid payload file arg",
|
||||
[]string{"bad-file", s.bondId},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
append([]string{recordFilePath, s.bondId}, s.commonTxFlags()...),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.SubTest(fmt.Sprintf("Case %s", tc.name), func(s *systemTestSuite) {
|
||||
cli := s.cli()
|
||||
cmd := append([]string{"tx", "registry", "set"}, tc.args...)
|
||||
if tc.err {
|
||||
cli := cli.WithRunErrorMatcher(assert.Error)
|
||||
_ = cli.RunCommandWithArgs(cmd...)
|
||||
} else {
|
||||
txhash := cli.Run(cmd...)
|
||||
systemtests.RequireTxSuccess(s.t, txhash)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func setupSuite(t *testing.T) *registryTestSuite {
|
||||
sut.ResetChain(t)
|
||||
|
||||
accountName := "node0"
|
||||
bondDenom := sdk.DefaultBondDenom
|
||||
var accountAddress string
|
||||
|
||||
s := newSystemTestSuite(t, "3"+bondDenom)
|
||||
|
||||
cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
|
||||
|
||||
sut.ModifyGenesisJSON(t, func(genesis []byte) []byte {
|
||||
accountAddress = s.cli().GetKeyAddr(accountName)
|
||||
|
||||
// update registry genesis params
|
||||
var regState registrytypes.GenesisState
|
||||
raw := gjson.Get(string(genesis), "app_state.registry").String()
|
||||
require.NoError(t, cdc.UnmarshalJSON([]byte(raw), ®State))
|
||||
|
||||
updateParams(®State.Params, bondDenom)
|
||||
regStateBz, err := cdc.MarshalJSON(®State)
|
||||
require.NoError(t, err)
|
||||
genesis, err = sjson.SetRawBytes(genesis, "app_state.registry", regStateBz)
|
||||
require.NoError(t, err)
|
||||
|
||||
// add consensus-controlled module account(s)
|
||||
bondinitmsg, err := codectypes.NewAnyWithValue(&nitrobank.MsgInitAccount{})
|
||||
require.NoError(t, err)
|
||||
var accountsState accountstypes.GenesisState
|
||||
raw = gjson.Get(string(genesis), "app_state.accounts").String()
|
||||
require.NoError(t, cdc.UnmarshalJSON([]byte(raw), &accountsState))
|
||||
accountsState.InitAccountMsgs = []*accountstypes.MsgInit{
|
||||
{
|
||||
Sender: accountAddress,
|
||||
AccountType: "nitrobank",
|
||||
Message: bondinitmsg,
|
||||
},
|
||||
}
|
||||
accountsStateBz, err := cdc.MarshalJSON(&accountsState)
|
||||
require.NoError(t, err)
|
||||
genesis, err = sjson.SetRawBytes(genesis, "app_state.accounts", accountsStateBz)
|
||||
require.NoError(t, err)
|
||||
|
||||
return genesis
|
||||
})
|
||||
sut.StartChain(t)
|
||||
|
||||
rts := registryTestSuite{
|
||||
systemTestSuite: s,
|
||||
accountName: accountName,
|
||||
accountAddress: accountAddress,
|
||||
bondDenom: bondDenom,
|
||||
}
|
||||
rts.bondId = createBond(&rts)
|
||||
return &rts
|
||||
}
|
||||
|
||||
func createBond(s *registryTestSuite) string {
|
||||
cli := s.cli()
|
||||
cmd := []string{
|
||||
"tx", "bond", "create",
|
||||
fmt.Sprintf("1000000%s", s.bondDenom),
|
||||
"--from", s.accountName,
|
||||
}
|
||||
txhash := cli.Run(cmd...)
|
||||
systemtests.RequireTxSuccess(s.t, txhash)
|
||||
|
||||
raw := cli.CustomQuery("q", "bond", "list")
|
||||
var queryResponse bondtypes.QueryBondsResponse
|
||||
require.NoError(s.t, json.Unmarshal([]byte(raw), &queryResponse))
|
||||
bonds := queryResponse.GetBonds()
|
||||
require.NotEmpty(s.t, bonds)
|
||||
return bonds[0].GetId()
|
||||
}
|
||||
|
||||
func reserveName(s *registryTestSuite, authorityName string) {
|
||||
cli := s.cli()
|
||||
cmd := []string{
|
||||
"tx", "registry", "reserve-authority",
|
||||
authorityName,
|
||||
s.accountAddress,
|
||||
}
|
||||
txhash := cli.Run(cmd...)
|
||||
systemtests.RequireTxSuccess(s.t, txhash)
|
||||
}
|
||||
|
||||
func createNameRecord(s *registryTestSuite, authorityName string) {
|
||||
cli := s.cli()
|
||||
// reserve name authority
|
||||
cmd := []string{
|
||||
"tx", "registry", "reserve-authority",
|
||||
authorityName,
|
||||
s.accountAddress,
|
||||
}
|
||||
txhash := cli.Run(cmd...)
|
||||
systemtests.RequireTxSuccess(s.t, txhash)
|
||||
|
||||
// add bond-id to name authority
|
||||
cmd = []string{
|
||||
"tx", "registry", "authority-bond",
|
||||
authorityName, s.bondId,
|
||||
}
|
||||
txhash = cli.Run(cmd...)
|
||||
systemtests.RequireTxSuccess(s.t, txhash)
|
||||
|
||||
cmd = []string{
|
||||
"tx", "registry", "set-name",
|
||||
fmt.Sprintf("lrn://%s/", authorityName),
|
||||
"test_hello_cid",
|
||||
}
|
||||
txhash = cli.Run(cmd...)
|
||||
systemtests.RequireTxSuccess(s.t, txhash)
|
||||
}
|
||||
|
||||
func createRecord(s *registryTestSuite, bondId string) {
|
||||
cmd := []string{
|
||||
"tx", "registry", "set",
|
||||
recordFilePath, bondId,
|
||||
}
|
||||
txhash := s.cli().Run(cmd...)
|
||||
systemtests.RequireTxSuccess(s.t, txhash)
|
||||
}
|
||||
|
||||
func updateParams(params *registrytypes.Params, bondDenom string) {
|
||||
params.RecordRent = sdk.NewCoin(bondDenom, math.NewInt(1000))
|
||||
params.RecordRentDuration = 10 * time.Second
|
||||
|
||||
params.AuthorityRent = sdk.NewCoin(bondDenom, math.NewInt(1000))
|
||||
params.AuthorityGracePeriod = 10 * time.Second
|
||||
|
||||
params.AuthorityAuctionCommitFee = sdk.NewCoin(bondDenom, math.NewInt(100))
|
||||
params.AuthorityAuctionRevealFee = sdk.NewCoin(bondDenom, math.NewInt(100))
|
||||
params.AuthorityAuctionMinimumBid = sdk.NewCoin(bondDenom, math.NewInt(500))
|
||||
}
|
||||
|
||||
func (s registryTestSuite) commonTxFlags() []string {
|
||||
return []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.accountName),
|
||||
// fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
// fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
// fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
// fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("3%s", s.bondDenom)),
|
||||
}
|
||||
}
|
||||
133
tests/system/test_runner.go
Normal file
133
tests/system/test_runner.go
Normal file
@ -0,0 +1,133 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var (
|
||||
sut *SystemUnderTest
|
||||
verbose bool
|
||||
execBinaryName = "laconicd"
|
||||
// block time (commit timeout) should match what the testnet command generates
|
||||
blockTime = time.Second
|
||||
)
|
||||
|
||||
func RunTests(m *testing.M) {
|
||||
waitTime := flag.Duration("wait-time", DefaultWaitTime, "time to wait for chain events")
|
||||
nodesCount := flag.Int("nodes-count", 4, "number of nodes in the cluster")
|
||||
// blockTime := flag.Duration("block-time", 1000*time.Millisecond, "block creation time")
|
||||
// execBinary := flag.String("binary", "simd", "executable binary for server/ client side")
|
||||
// bech32Prefix := flag.String("bech32", "cosmos", "bech32 prefix to be used with addresses")
|
||||
flag.BoolVar(&verbose, "verbose", false, "verbose output")
|
||||
flag.Parse()
|
||||
|
||||
// fail fast on most common setup issue
|
||||
requireEnoughFileHandlers(*nodesCount + 1) // +1 as tests may start another node
|
||||
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
WorkDir = dir
|
||||
if verbose {
|
||||
println("Work dir: ", WorkDir)
|
||||
}
|
||||
initSDKConfig("laconic")
|
||||
|
||||
DefaultWaitTime = *waitTime
|
||||
// if *execBinary == "" {
|
||||
// panic("executable binary name must not be empty")
|
||||
// }
|
||||
|
||||
// sdk systemtests expects this to be set for v2 server/runtime
|
||||
os.Setenv("COSMOS_BUILD_OPTIONS", "v2")
|
||||
|
||||
sut = NewSystemUnderTest(execBinaryName, verbose, *nodesCount, blockTime)
|
||||
sut.SetupChain() // setup chain and keyring
|
||||
|
||||
// run tests
|
||||
exitCode := m.Run()
|
||||
|
||||
// postprocess
|
||||
sut.StopChain()
|
||||
if verbose || exitCode != 0 {
|
||||
sut.PrintBuffer()
|
||||
printResultFlag(exitCode == 0)
|
||||
}
|
||||
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
func GetSystemUnderTest() *SystemUnderTest {
|
||||
return sut
|
||||
}
|
||||
|
||||
func IsVerbose() bool {
|
||||
return verbose
|
||||
}
|
||||
|
||||
func GetExecutableName() string {
|
||||
return execBinaryName
|
||||
}
|
||||
|
||||
// requireEnoughFileHandlers uses `ulimit`
|
||||
func requireEnoughFileHandlers(nodesCount int) {
|
||||
ulimit, err := exec.LookPath("ulimit")
|
||||
if err != nil || ulimit == "" { // skip when not available
|
||||
return
|
||||
}
|
||||
|
||||
cmd := exec.Command(ulimit, "-n")
|
||||
cmd.Dir = WorkDir
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unexpected error :%#+v, output: %s", err, string(out)))
|
||||
}
|
||||
fileDescrCount, err := strconv.Atoi(strings.Trim(string(out), " \t\n"))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unexpected error :%#+v, output: %s", err, string(out)))
|
||||
}
|
||||
expFH := nodesCount * 260 // random number that worked on my box
|
||||
if fileDescrCount < expFH {
|
||||
panic(fmt.Sprintf("Fail fast. Insufficient setup. Run 'ulimit -n %d'", expFH))
|
||||
}
|
||||
}
|
||||
|
||||
func initSDKConfig(bech32Prefix string) {
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(bech32Prefix, bech32Prefix+sdk.PrefixPublic)
|
||||
config.SetBech32PrefixForValidator(bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator, bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic)
|
||||
config.SetBech32PrefixForConsensusNode(bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus, bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic)
|
||||
}
|
||||
|
||||
const (
|
||||
successFlag = `
|
||||
___ _ _ ___ ___ ___ ___ ___
|
||||
/ __| | | |/ __/ __/ _ \/ __/ __|
|
||||
\__ \ |_| | (_| (_| __/\__ \__ \
|
||||
|___/\__,_|\___\___\___||___/___/`
|
||||
failureFlag = `
|
||||
__ _ _ _
|
||||
/ _| (_) | | |
|
||||
| |_ __ _ _| | ___ __| |
|
||||
| _/ _| | | |/ _ \/ _| |
|
||||
| || (_| | | | __/ (_| |
|
||||
|_| \__,_|_|_|\___|\__,_|`
|
||||
)
|
||||
|
||||
func printResultFlag(ok bool) {
|
||||
if ok {
|
||||
fmt.Println(successFlag)
|
||||
} else {
|
||||
fmt.Println(failureFlag)
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/testutil/network"
|
||||
)
|
||||
|
||||
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.50.3/testutil/cli/tx.go#L15
|
||||
|
||||
// CheckTxCode verifies that the transaction result returns a specific code
|
||||
// Takes a network, wait for two blocks and fetch the transaction from its hash
|
||||
func CheckTxCode(network *network.Network, clientCtx client.Context, txHash string, expectedCode uint32) error {
|
||||
// wait for 2 blocks
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := network.WaitForNextBlock(); err != nil {
|
||||
return fmt.Errorf("failed to wait for next block: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := authcli.QueryTxCmd()
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{txHash, fmt.Sprintf("--%s=json", flags.FlagOutput)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var response sdk.TxResponse
|
||||
if err := clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if response.Code != expectedCode {
|
||||
return fmt.Errorf("expected code %d, got %d", expectedCode, response.Code)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
15
testutil/keyring.go
Normal file
15
testutil/keyring.go
Normal file
@ -0,0 +1,15 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
modtestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/utils"
|
||||
)
|
||||
|
||||
func NewKeyring() keyring.Keyring {
|
||||
codecOpts := codectestutil.NewCodecOptionsWithCodecs(utils.NewAddressCodec(), utils.NewValAddressCodec())
|
||||
encCfg := modtestutil.MakeTestEncodingConfig(codecOpts)
|
||||
return keyring.NewInMemory(encCfg.Codec)
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
/*
|
||||
Package network implements and exposes a fully operational in-process CometBFT
|
||||
test network that consists of at least one or potentially many validators. This
|
||||
test network can be used primarily for integration tests or unit test suites.
|
||||
|
||||
The test network utilizes SimApp as the ABCI application and uses all the modules
|
||||
defined in the Cosmos SDK. An in-process test network can be configured with any
|
||||
number of validators as well as account funds and even custom genesis state.
|
||||
|
||||
When creating a test network, a series of Validator objects are returned. Each
|
||||
Validator object has useful information such as their address and public key. A
|
||||
Validator will also provide its RPC, P2P, and API addresses that can be useful
|
||||
for integration testing. In addition, a CometBFT local RPC client is also provided
|
||||
which can be handy for making direct RPC calls to CometBFT.
|
||||
|
||||
Note, due to limitations in concurrency and the design of the RPC layer in
|
||||
CometBFT, only the first Validator object will have an RPC and API client
|
||||
exposed. Due to this exact same limitation, only a single test network can exist
|
||||
at a time. A caller must be certain it calls Cleanup after it no longer needs
|
||||
the network.
|
||||
|
||||
A typical testing flow might look like the following:
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) SetupSuite() {
|
||||
s.T().Log("setting up integration test suite")
|
||||
|
||||
cfg := network.DefaultConfig()
|
||||
cfg.NumValidators = 1
|
||||
s.cfg = cfg
|
||||
|
||||
var err error
|
||||
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down integration test suite")
|
||||
|
||||
// This is important and must be called to ensure other tests can create
|
||||
// a network!
|
||||
s.network.Cleanup()
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestQueryBalancesRequestHandlerFn() {
|
||||
val := s.network.Validators[0]
|
||||
baseURL := val.APIAddress
|
||||
|
||||
// Use baseURL to make API HTTP requests or use val.RPCClient to make direct
|
||||
// CometBFT RPC calls.
|
||||
// ...
|
||||
}
|
||||
|
||||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
}
|
||||
*/
|
||||
package network
|
||||
|
||||
/*
|
||||
NOTE:
|
||||
Copied over from https://github.com/cosmos/cosmos-sdk/tree/v0.50.3/testutil/network
|
||||
Patch:
|
||||
- Skipped network.LatestHeight() call at the end of New()
|
||||
- Removed block timeouts
|
||||
*/
|
||||
@ -1,852 +0,0 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cometbft/cometbft/node"
|
||||
cmtclient "github.com/cometbft/cometbft/rpc/client"
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"cosmossdk.io/math/unsafe"
|
||||
pruningtypes "cosmossdk.io/store/pruning/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/server/api"
|
||||
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth" // import auth as a blank
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import auth tx config as a blank
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/bank" // import bank as a blank
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/consensus" // import consensus as a blank
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/params" // import params as a blank
|
||||
_ "github.com/cosmos/cosmos-sdk/x/staking" // import staking as a blank
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// package-wide network lock to only allow one test network at a time
|
||||
var (
|
||||
lock = new(sync.Mutex)
|
||||
portPool = make(chan string, 200)
|
||||
)
|
||||
|
||||
func init() {
|
||||
closeFns := []func() error{}
|
||||
for i := 0; i < 200; i++ {
|
||||
_, port, closeFn, err := FreeTCPAddr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
portPool <- port
|
||||
closeFns = append(closeFns, closeFn)
|
||||
}
|
||||
|
||||
for _, closeFn := range closeFns {
|
||||
err := closeFn()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AppConstructor defines a function which accepts a network configuration and
|
||||
// creates an ABCI Application to provide to CometBFT.
|
||||
type (
|
||||
AppConstructor = func(val ValidatorI) servertypes.Application
|
||||
TestFixtureFactory = func() TestFixture
|
||||
)
|
||||
|
||||
type TestFixture struct {
|
||||
AppConstructor AppConstructor
|
||||
GenesisState map[string]json.RawMessage
|
||||
EncodingConfig moduletestutil.TestEncodingConfig
|
||||
}
|
||||
|
||||
// Config defines the necessary configuration used to bootstrap and start an
|
||||
// in-process local testing network.
|
||||
type Config struct {
|
||||
Codec codec.Codec
|
||||
LegacyAmino *codec.LegacyAmino // TODO: Remove!
|
||||
InterfaceRegistry codectypes.InterfaceRegistry
|
||||
|
||||
TxConfig client.TxConfig
|
||||
AccountRetriever client.AccountRetriever
|
||||
AppConstructor AppConstructor // the ABCI application constructor
|
||||
GenesisState map[string]json.RawMessage // custom genesis state to provide
|
||||
TimeoutCommit time.Duration // the consensus commitment timeout
|
||||
ChainID string // the network chain-id
|
||||
NumValidators int // the total number of validators to create and bond
|
||||
Mnemonics []string // custom user-provided validator operator mnemonics
|
||||
BondDenom string // the staking bond denomination
|
||||
MinGasPrices string // the minimum gas prices each validator will accept
|
||||
AccountTokens sdkmath.Int // the amount of unique validator tokens (e.g. 1000node0)
|
||||
StakingTokens sdkmath.Int // the amount of tokens each validator has available to stake
|
||||
BondedTokens sdkmath.Int // the amount of tokens each validator stakes
|
||||
PruningStrategy string // the pruning strategy each validator will have
|
||||
EnableLogging bool // enable logging to STDOUT
|
||||
CleanupDir bool // remove base temporary directory during cleanup
|
||||
SigningAlgo string // signing algorithm for keys
|
||||
KeyringOptions []keyring.Option // keyring configuration options
|
||||
RPCAddress string // RPC listen address (including port)
|
||||
APIAddress string // REST API listen address (including port)
|
||||
GRPCAddress string // GRPC server listen address (including port)
|
||||
PrintMnemonic bool // print the mnemonic of first validator as log output for testing
|
||||
}
|
||||
|
||||
// DefaultConfig returns a sane default configuration suitable for nearly all
|
||||
// testing requirements.
|
||||
func DefaultConfig(factory TestFixtureFactory) Config {
|
||||
fixture := factory()
|
||||
|
||||
return Config{
|
||||
Codec: fixture.EncodingConfig.Codec,
|
||||
TxConfig: fixture.EncodingConfig.TxConfig,
|
||||
LegacyAmino: fixture.EncodingConfig.Amino,
|
||||
InterfaceRegistry: fixture.EncodingConfig.InterfaceRegistry,
|
||||
AccountRetriever: authtypes.AccountRetriever{},
|
||||
AppConstructor: fixture.AppConstructor,
|
||||
GenesisState: fixture.GenesisState,
|
||||
TimeoutCommit: 2 * time.Second,
|
||||
ChainID: "chain-" + unsafe.Str(6),
|
||||
NumValidators: 4,
|
||||
BondDenom: sdk.DefaultBondDenom,
|
||||
MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
|
||||
AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction),
|
||||
StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction),
|
||||
BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction),
|
||||
PruningStrategy: pruningtypes.PruningOptionNothing,
|
||||
CleanupDir: true,
|
||||
SigningAlgo: string(hd.Secp256k1Type),
|
||||
KeyringOptions: []keyring.Option{},
|
||||
PrintMnemonic: false,
|
||||
}
|
||||
}
|
||||
|
||||
// MinimumAppConfig defines the minimum of modules required for a call to New to succeed
|
||||
func MinimumAppConfig() depinject.Config {
|
||||
return configurator.NewAppConfig(
|
||||
configurator.AuthModule(),
|
||||
configurator.ParamsModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.GenutilModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.TxModule(),
|
||||
)
|
||||
}
|
||||
|
||||
func DefaultConfigWithAppConfig(appConfig depinject.Config) (Config, error) {
|
||||
var (
|
||||
appBuilder *runtime.AppBuilder
|
||||
txConfig client.TxConfig
|
||||
legacyAmino *codec.LegacyAmino
|
||||
cdc codec.Codec
|
||||
interfaceRegistry codectypes.InterfaceRegistry
|
||||
)
|
||||
|
||||
if err := depinject.Inject(
|
||||
depinject.Configs(
|
||||
appConfig,
|
||||
depinject.Supply(log.NewNopLogger()),
|
||||
),
|
||||
&appBuilder,
|
||||
&txConfig,
|
||||
&cdc,
|
||||
&legacyAmino,
|
||||
&interfaceRegistry,
|
||||
); err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
|
||||
cfg := DefaultConfig(func() TestFixture {
|
||||
return TestFixture{}
|
||||
})
|
||||
cfg.Codec = cdc
|
||||
cfg.TxConfig = txConfig
|
||||
cfg.LegacyAmino = legacyAmino
|
||||
cfg.InterfaceRegistry = interfaceRegistry
|
||||
cfg.GenesisState = appBuilder.DefaultGenesis()
|
||||
cfg.AppConstructor = func(val ValidatorI) servertypes.Application {
|
||||
// we build a unique app instance for every validator here
|
||||
var appBuilder *runtime.AppBuilder
|
||||
if err := depinject.Inject(
|
||||
depinject.Configs(
|
||||
appConfig,
|
||||
depinject.Supply(val.GetCtx().Logger),
|
||||
),
|
||||
&appBuilder); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
app := appBuilder.Build(
|
||||
dbm.NewMemDB(),
|
||||
nil,
|
||||
baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.GetAppConfig().Pruning)),
|
||||
baseapp.SetMinGasPrices(val.GetAppConfig().MinGasPrices),
|
||||
baseapp.SetChainID(cfg.ChainID),
|
||||
)
|
||||
|
||||
testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{})
|
||||
|
||||
if err := app.Load(true); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
type (
|
||||
// Network defines a local in-process testing network using SimApp. It can be
|
||||
// configured to start any number of validators, each with its own RPC and API
|
||||
// clients. Typically, this test network would be used in client and integration
|
||||
// testing where user input is expected.
|
||||
//
|
||||
// Note, due to CometBFT constraints in regards to RPC functionality, there
|
||||
// may only be one test network running at a time. Thus, any caller must be
|
||||
// sure to Cleanup after testing is finished in order to allow other tests
|
||||
// to create networks. In addition, only the first validator will have a valid
|
||||
// RPC and API server/client.
|
||||
Network struct {
|
||||
Logger Logger
|
||||
BaseDir string
|
||||
Validators []*Validator
|
||||
|
||||
Config Config
|
||||
}
|
||||
|
||||
// Validator defines an in-process CometBFT validator node. Through this object,
|
||||
// a client can make RPC and API calls and interact with any client command
|
||||
// or handler.
|
||||
Validator struct {
|
||||
AppConfig *srvconfig.Config
|
||||
ClientCtx client.Context
|
||||
Ctx *server.Context
|
||||
Dir string
|
||||
NodeID string
|
||||
PubKey cryptotypes.PubKey
|
||||
Moniker string
|
||||
APIAddress string
|
||||
RPCAddress string
|
||||
P2PAddress string
|
||||
Address sdk.AccAddress
|
||||
ValAddress sdk.ValAddress
|
||||
RPCClient cmtclient.Client
|
||||
|
||||
app servertypes.Application
|
||||
tmNode *node.Node
|
||||
api *api.Server
|
||||
grpc *grpc.Server
|
||||
grpcWeb *http.Server
|
||||
errGroup *errgroup.Group
|
||||
cancelFn context.CancelFunc
|
||||
}
|
||||
|
||||
// ValidatorI expose a validator's context and configuration
|
||||
ValidatorI interface {
|
||||
GetCtx() *server.Context
|
||||
GetAppConfig() *srvconfig.Config
|
||||
}
|
||||
|
||||
// Logger is a network logger interface that exposes testnet-level Log() methods for an in-process testing network
|
||||
// This is not to be confused with logging that may happen at an individual node or validator level
|
||||
Logger interface {
|
||||
Log(args ...interface{})
|
||||
Logf(format string, args ...interface{})
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
_ Logger = (*testing.T)(nil)
|
||||
_ Logger = (*CLILogger)(nil)
|
||||
_ ValidatorI = Validator{}
|
||||
)
|
||||
|
||||
func (v Validator) GetCtx() *server.Context {
|
||||
return v.Ctx
|
||||
}
|
||||
|
||||
func (v Validator) GetAppConfig() *srvconfig.Config {
|
||||
return v.AppConfig
|
||||
}
|
||||
|
||||
// CLILogger wraps a cobra.Command and provides command logging methods.
|
||||
type CLILogger struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
// Log logs given args.
|
||||
func (s CLILogger) Log(args ...interface{}) {
|
||||
s.cmd.Println(args...)
|
||||
}
|
||||
|
||||
// Logf logs given args according to a format specifier.
|
||||
func (s CLILogger) Logf(format string, args ...interface{}) {
|
||||
s.cmd.Printf(format, args...)
|
||||
}
|
||||
|
||||
// NewCLILogger creates a new CLILogger.
|
||||
func NewCLILogger(cmd *cobra.Command) CLILogger {
|
||||
return CLILogger{cmd}
|
||||
}
|
||||
|
||||
// New creates a new Network for integration tests or in-process testnets run via the CLI
|
||||
func New(l Logger, baseDir string, cfg Config) (*Network, error) {
|
||||
// only one caller/test can create and use a network at a time
|
||||
l.Log("acquiring test network lock")
|
||||
lock.Lock()
|
||||
|
||||
network := &Network{
|
||||
Logger: l,
|
||||
BaseDir: baseDir,
|
||||
Validators: make([]*Validator, cfg.NumValidators),
|
||||
Config: cfg,
|
||||
}
|
||||
|
||||
l.Logf("preparing test network with chain-id \"%s\"\n", cfg.ChainID)
|
||||
|
||||
monikers := make([]string, cfg.NumValidators)
|
||||
nodeIDs := make([]string, cfg.NumValidators)
|
||||
valPubKeys := make([]cryptotypes.PubKey, cfg.NumValidators)
|
||||
|
||||
var (
|
||||
genAccounts []authtypes.GenesisAccount
|
||||
genBalances []banktypes.Balance
|
||||
genFiles []string
|
||||
)
|
||||
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
|
||||
// generate private keys, node IDs, and initial transactions
|
||||
for i := 0; i < cfg.NumValidators; i++ {
|
||||
appCfg := srvconfig.DefaultConfig()
|
||||
appCfg.Pruning = cfg.PruningStrategy
|
||||
appCfg.MinGasPrices = cfg.MinGasPrices
|
||||
appCfg.API.Enable = true
|
||||
appCfg.API.Swagger = false
|
||||
appCfg.Telemetry.Enabled = false
|
||||
|
||||
ctx := server.NewDefaultContext()
|
||||
cmtCfg := ctx.Config
|
||||
cmtCfg.Consensus.TimeoutCommit = cfg.TimeoutCommit
|
||||
|
||||
// Only allow the first validator to expose an RPC, API and gRPC
|
||||
// server/client due to CometBFT in-process constraints.
|
||||
apiAddr := ""
|
||||
cmtCfg.RPC.ListenAddress = ""
|
||||
appCfg.GRPC.Enable = false
|
||||
appCfg.GRPCWeb.Enable = false
|
||||
apiListenAddr := ""
|
||||
if i == 0 {
|
||||
if cfg.APIAddress != "" {
|
||||
apiListenAddr = cfg.APIAddress
|
||||
} else {
|
||||
if len(portPool) == 0 {
|
||||
return nil, fmt.Errorf("failed to get port for API server")
|
||||
}
|
||||
port := <-portPool
|
||||
apiListenAddr = fmt.Sprintf("tcp://0.0.0.0:%s", port)
|
||||
}
|
||||
|
||||
appCfg.API.Address = apiListenAddr
|
||||
apiURL, err := url.Parse(apiListenAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiAddr = fmt.Sprintf("http://%s:%s", apiURL.Hostname(), apiURL.Port())
|
||||
|
||||
if cfg.RPCAddress != "" {
|
||||
cmtCfg.RPC.ListenAddress = cfg.RPCAddress
|
||||
} else {
|
||||
if len(portPool) == 0 {
|
||||
return nil, fmt.Errorf("failed to get port for RPC server")
|
||||
}
|
||||
port := <-portPool
|
||||
cmtCfg.RPC.ListenAddress = fmt.Sprintf("tcp://0.0.0.0:%s", port)
|
||||
}
|
||||
|
||||
if cfg.GRPCAddress != "" {
|
||||
appCfg.GRPC.Address = cfg.GRPCAddress
|
||||
} else {
|
||||
if len(portPool) == 0 {
|
||||
return nil, fmt.Errorf("failed to get port for GRPC server")
|
||||
}
|
||||
port := <-portPool
|
||||
appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", port)
|
||||
}
|
||||
appCfg.GRPC.Enable = true
|
||||
appCfg.GRPCWeb.Enable = true
|
||||
}
|
||||
|
||||
logger := log.NewNopLogger()
|
||||
if cfg.EnableLogging {
|
||||
logger = log.NewLogger(os.Stdout) // TODO(mr): enable selection of log destination.
|
||||
}
|
||||
|
||||
ctx.Logger = logger
|
||||
|
||||
nodeDirName := fmt.Sprintf("node%d", i)
|
||||
nodeDir := filepath.Join(network.BaseDir, nodeDirName, "simd")
|
||||
clientDir := filepath.Join(network.BaseDir, nodeDirName, "simcli")
|
||||
gentxsDir := filepath.Join(network.BaseDir, "gentxs")
|
||||
|
||||
err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(clientDir, 0o755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmtCfg.SetRoot(nodeDir)
|
||||
cmtCfg.Moniker = nodeDirName
|
||||
monikers[i] = nodeDirName
|
||||
|
||||
if len(portPool) == 0 {
|
||||
return nil, fmt.Errorf("failed to get port for Proxy server")
|
||||
}
|
||||
port := <-portPool
|
||||
proxyAddr := fmt.Sprintf("tcp://0.0.0.0:%s", port)
|
||||
cmtCfg.ProxyApp = proxyAddr
|
||||
|
||||
if len(portPool) == 0 {
|
||||
return nil, fmt.Errorf("failed to get port for Proxy server")
|
||||
}
|
||||
port = <-portPool
|
||||
p2pAddr := fmt.Sprintf("tcp://0.0.0.0:%s", port)
|
||||
cmtCfg.P2P.ListenAddress = p2pAddr
|
||||
cmtCfg.P2P.AddrBookStrict = false
|
||||
cmtCfg.P2P.AllowDuplicateIP = true
|
||||
|
||||
nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(cmtCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeIDs[i] = nodeID
|
||||
valPubKeys[i] = pubKey
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var mnemonic string
|
||||
if i < len(cfg.Mnemonics) {
|
||||
mnemonic = cfg.Mnemonics[i]
|
||||
}
|
||||
|
||||
addr, secret, err := testutil.GenerateSaveCoinKey(kb, nodeDirName, mnemonic, true, algo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if PrintMnemonic is set to true, we print the first validator node's secret to the network's logger
|
||||
// for debugging and manual testing
|
||||
if cfg.PrintMnemonic && i == 0 {
|
||||
printMnemonic(l, secret)
|
||||
}
|
||||
|
||||
info := map[string]string{"secret": secret}
|
||||
infoBz, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// save private key seed words
|
||||
err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
balances := sdk.NewCoins(
|
||||
sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens),
|
||||
sdk.NewCoin(cfg.BondDenom, cfg.StakingTokens),
|
||||
)
|
||||
|
||||
genFiles = append(genFiles, cmtCfg.GenesisFile())
|
||||
genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: balances.Sort()})
|
||||
genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0))
|
||||
|
||||
commission, err := sdkmath.LegacyNewDecFromStr("0.5")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
createValMsg, err := stakingtypes.NewMsgCreateValidator(
|
||||
sdk.ValAddress(addr).String(),
|
||||
valPubKeys[i],
|
||||
sdk.NewCoin(cfg.BondDenom, cfg.BondedTokens),
|
||||
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
|
||||
stakingtypes.NewCommissionRates(commission, sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec()),
|
||||
sdkmath.OneInt(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p2pURL, err := url.Parse(p2pAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port())
|
||||
fee := sdk.NewCoins(sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), sdkmath.NewInt(0)))
|
||||
txBuilder := cfg.TxConfig.NewTxBuilder()
|
||||
err = txBuilder.SetMsgs(createValMsg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txBuilder.SetFeeAmount(fee) // Arbitrary fee
|
||||
txBuilder.SetGasLimit(1000000) // Need at least 100386
|
||||
txBuilder.SetMemo(memo)
|
||||
|
||||
txFactory := tx.Factory{}
|
||||
txFactory = txFactory.
|
||||
WithChainID(cfg.ChainID).
|
||||
WithMemo(memo).
|
||||
WithKeybase(kb).
|
||||
WithTxConfig(cfg.TxConfig)
|
||||
|
||||
err = tx.Sign(context.Background(), txFactory, nodeDirName, txBuilder, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config", "app.toml"), appCfg)
|
||||
|
||||
clientCtx := client.Context{}.
|
||||
WithKeyringDir(clientDir).
|
||||
WithKeyring(kb).
|
||||
WithHomeDir(cmtCfg.RootDir).
|
||||
WithChainID(cfg.ChainID).
|
||||
WithInterfaceRegistry(cfg.InterfaceRegistry).
|
||||
WithCodec(cfg.Codec).
|
||||
WithLegacyAmino(cfg.LegacyAmino).
|
||||
WithTxConfig(cfg.TxConfig).
|
||||
WithAccountRetriever(cfg.AccountRetriever).
|
||||
WithNodeURI(cmtCfg.RPC.ListenAddress)
|
||||
|
||||
// Provide ChainID here since we can't modify it in the Comet config.
|
||||
ctx.Viper.Set(flags.FlagChainID, cfg.ChainID)
|
||||
|
||||
network.Validators[i] = &Validator{
|
||||
AppConfig: appCfg,
|
||||
ClientCtx: clientCtx,
|
||||
Ctx: ctx,
|
||||
Dir: filepath.Join(network.BaseDir, nodeDirName),
|
||||
NodeID: nodeID,
|
||||
PubKey: pubKey,
|
||||
Moniker: nodeDirName,
|
||||
RPCAddress: cmtCfg.RPC.ListenAddress,
|
||||
P2PAddress: cmtCfg.P2P.ListenAddress,
|
||||
APIAddress: apiAddr,
|
||||
Address: addr,
|
||||
ValAddress: sdk.ValAddress(addr),
|
||||
}
|
||||
}
|
||||
|
||||
err := initGenFiles(cfg, genAccounts, genBalances, genFiles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = collectGenFiles(cfg, network.Validators, network.BaseDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l.Log("starting test network...")
|
||||
for idx, v := range network.Validators {
|
||||
if err := startInProcess(cfg, v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.Log("started validator", idx)
|
||||
}
|
||||
|
||||
// height, err := network.LatestHeight()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// l.Log("started test network at height:", height)
|
||||
|
||||
// Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any
|
||||
// defer in a test would not be called.
|
||||
trapSignal(network.Cleanup)
|
||||
|
||||
return network, nil
|
||||
}
|
||||
|
||||
// trapSignal traps SIGINT and SIGTERM and calls os.Exit once a signal is received.
|
||||
func trapSignal(cleanupFunc func()) {
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
sig := <-sigs
|
||||
|
||||
if cleanupFunc != nil {
|
||||
cleanupFunc()
|
||||
}
|
||||
exitCode := 128
|
||||
|
||||
switch sig {
|
||||
case syscall.SIGINT:
|
||||
exitCode += int(syscall.SIGINT)
|
||||
case syscall.SIGTERM:
|
||||
exitCode += int(syscall.SIGTERM)
|
||||
}
|
||||
|
||||
os.Exit(exitCode)
|
||||
}()
|
||||
}
|
||||
|
||||
// LatestHeight returns the latest height of the network or an error if the
|
||||
// query fails or no validators exist.
|
||||
func (n *Network) LatestHeight() (int64, error) {
|
||||
if len(n.Validators) == 0 {
|
||||
return 0, errors.New("no validators available")
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
timeout := time.NewTimer(time.Second * 5)
|
||||
defer timeout.Stop()
|
||||
|
||||
var latestHeight int64
|
||||
val := n.Validators[0]
|
||||
queryClient := cmtservice.NewServiceClient(val.ClientCtx)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
res, err := queryClient.GetLatestBlock(context.Background(), &cmtservice.GetLatestBlockRequest{})
|
||||
if err == nil && res != nil {
|
||||
latestHeight = res.SdkBlock.Header.Height
|
||||
}
|
||||
done <- struct{}{}
|
||||
}()
|
||||
select {
|
||||
case <-timeout.C:
|
||||
return latestHeight, errors.New("timeout exceeded waiting for block")
|
||||
case <-done:
|
||||
if latestHeight != 0 {
|
||||
return latestHeight, nil
|
||||
}
|
||||
}
|
||||
default: //nolint: all
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForHeight performs a blocking check where it waits for a block to be
|
||||
// committed after a given block.
|
||||
func (n *Network) WaitForHeight(h int64) (int64, error) {
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
if len(n.Validators) == 0 {
|
||||
return 0, errors.New("no validators available")
|
||||
}
|
||||
|
||||
var latestHeight int64
|
||||
val := n.Validators[0]
|
||||
queryClient := cmtservice.NewServiceClient(val.ClientCtx)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
|
||||
res, err := queryClient.GetLatestBlock(context.Background(), &cmtservice.GetLatestBlockRequest{})
|
||||
if err == nil && res != nil {
|
||||
latestHeight = res.GetSdkBlock().Header.Height
|
||||
if latestHeight >= h {
|
||||
return latestHeight, nil
|
||||
}
|
||||
}
|
||||
default: //nolint: all
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RetryForBlocks will wait for the next block and execute the function provided.
|
||||
// It will do this until the function returns a nil error or until the number of
|
||||
// blocks has been reached.
|
||||
func (n *Network) RetryForBlocks(retryFunc func() error, blocks int) error {
|
||||
for i := 0; i < blocks; i++ {
|
||||
_ = n.WaitForNextBlock()
|
||||
err := retryFunc()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
// we've reached the last block to wait, return the error
|
||||
if i == blocks-1 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitForNextBlock waits for the next block to be committed, returning an error
|
||||
// upon failure.
|
||||
func (n *Network) WaitForNextBlock() error {
|
||||
lastBlock, err := n.LatestHeight()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = n.WaitForHeight(lastBlock + 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Cleanup removes the root testing (temporary) directory and stops both the
|
||||
// CometBFT and API services. It allows other callers to create and start
|
||||
// test networks. This method must be called when a test is finished, typically
|
||||
// in a defer.
|
||||
func (n *Network) Cleanup() {
|
||||
defer func() {
|
||||
lock.Unlock()
|
||||
n.Logger.Log("released test network lock")
|
||||
}()
|
||||
|
||||
n.Logger.Log("cleaning up test network...")
|
||||
|
||||
for _, v := range n.Validators {
|
||||
// cancel the validator's context which will signal to the gRPC and API
|
||||
// goroutines that they should gracefully exit.
|
||||
v.cancelFn()
|
||||
|
||||
if err := v.errGroup.Wait(); err != nil {
|
||||
n.Logger.Log("unexpected error waiting for validator gRPC and API processes to exit", "err", err)
|
||||
}
|
||||
|
||||
if v.tmNode != nil && v.tmNode.IsRunning() {
|
||||
if err := v.tmNode.Stop(); err != nil {
|
||||
n.Logger.Log("failed to stop validator CometBFT node", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
if v.grpcWeb != nil {
|
||||
_ = v.grpcWeb.Close()
|
||||
}
|
||||
|
||||
if v.app != nil {
|
||||
if err := v.app.Close(); err != nil {
|
||||
n.Logger.Log("failed to stop validator ABCI application", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
if n.Config.CleanupDir {
|
||||
_ = os.RemoveAll(n.BaseDir)
|
||||
}
|
||||
|
||||
n.Logger.Log("finished cleaning up test network")
|
||||
}
|
||||
|
||||
// printMnemonic prints a provided mnemonic seed phrase on a network logger
|
||||
// for debugging and manual testing
|
||||
func printMnemonic(l Logger, secret string) {
|
||||
lines := []string{
|
||||
"THIS MNEMONIC IS FOR TESTING PURPOSES ONLY",
|
||||
"DO NOT USE IN PRODUCTION",
|
||||
"",
|
||||
strings.Join(strings.Fields(secret)[0:8], " "),
|
||||
strings.Join(strings.Fields(secret)[8:16], " "),
|
||||
strings.Join(strings.Fields(secret)[16:24], " "),
|
||||
}
|
||||
|
||||
lineLengths := make([]int, len(lines))
|
||||
for i, line := range lines {
|
||||
lineLengths[i] = len(line)
|
||||
}
|
||||
|
||||
maxLineLength := 0
|
||||
for _, lineLen := range lineLengths {
|
||||
if lineLen > maxLineLength {
|
||||
maxLineLength = lineLen
|
||||
}
|
||||
}
|
||||
|
||||
l.Log("\n")
|
||||
l.Log(strings.Repeat("+", maxLineLength+8))
|
||||
for _, line := range lines {
|
||||
l.Logf("++ %s ++\n", centerText(line, maxLineLength))
|
||||
}
|
||||
l.Log(strings.Repeat("+", maxLineLength+8))
|
||||
l.Log("\n")
|
||||
}
|
||||
|
||||
// centerText centers text across a fixed width, filling either side with whitespace buffers
|
||||
func centerText(text string, width int) string {
|
||||
textLen := len(text)
|
||||
leftBuffer := strings.Repeat(" ", (width-textLen)/2)
|
||||
rightBuffer := strings.Repeat(" ", (width-textLen)/2+(width-textLen)%2)
|
||||
|
||||
return fmt.Sprintf("%s%s%s", leftBuffer, text, rightBuffer)
|
||||
}
|
||||
@ -1,240 +0,0 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
cmtcfg "github.com/cometbft/cometbft/config"
|
||||
"github.com/cometbft/cometbft/node"
|
||||
"github.com/cometbft/cometbft/p2p"
|
||||
pvm "github.com/cometbft/cometbft/privval"
|
||||
"github.com/cometbft/cometbft/proxy"
|
||||
"github.com/cometbft/cometbft/rpc/client/local"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
cmttime "github.com/cometbft/cometbft/types/time"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/server/api"
|
||||
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
|
||||
servercmtlog "github.com/cosmos/cosmos-sdk/server/log"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
func startInProcess(cfg Config, val *Validator) error {
|
||||
logger := val.Ctx.Logger
|
||||
cmtCfg := val.Ctx.Config
|
||||
cmtCfg.Instrumentation.Prometheus = false
|
||||
|
||||
if err := val.AppConfig.ValidateBasic(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(cmtCfg.NodeKeyFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app := cfg.AppConstructor(*val)
|
||||
val.app = app
|
||||
|
||||
appGenesisProvider := func() (*cmttypes.GenesisDoc, error) {
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(cmtCfg.GenesisFile())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return appGenesis.ToGenesisDoc()
|
||||
}
|
||||
|
||||
cmtApp := server.NewCometABCIWrapper(app)
|
||||
tmNode, err := node.NewNode( //resleak:notresource
|
||||
cmtCfg,
|
||||
pvm.LoadOrGenFilePV(cmtCfg.PrivValidatorKeyFile(), cmtCfg.PrivValidatorStateFile()),
|
||||
nodeKey,
|
||||
proxy.NewLocalClientCreator(cmtApp),
|
||||
appGenesisProvider,
|
||||
cmtcfg.DefaultDBProvider,
|
||||
node.DefaultMetricsProvider(cmtCfg.Instrumentation),
|
||||
servercmtlog.CometLoggerWrapper{Logger: logger.With("module", val.Moniker)},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tmNode.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
val.tmNode = tmNode
|
||||
|
||||
if val.RPCAddress != "" {
|
||||
val.RPCClient = local.New(tmNode)
|
||||
}
|
||||
|
||||
// We'll need a RPC client if the validator exposes a gRPC or REST endpoint.
|
||||
if val.APIAddress != "" || val.AppConfig.GRPC.Enable {
|
||||
val.ClientCtx = val.ClientCtx.
|
||||
WithClient(val.RPCClient)
|
||||
|
||||
app.RegisterTxService(val.ClientCtx)
|
||||
app.RegisterTendermintService(val.ClientCtx)
|
||||
app.RegisterNodeService(val.ClientCtx, *val.AppConfig)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, val.cancelFn = context.WithCancel(ctx)
|
||||
val.errGroup, ctx = errgroup.WithContext(ctx)
|
||||
|
||||
grpcCfg := val.AppConfig.GRPC
|
||||
|
||||
if grpcCfg.Enable {
|
||||
grpcSrv, err := servergrpc.NewGRPCServer(val.ClientCtx, app, grpcCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start the gRPC server in a goroutine. Note, the provided ctx will ensure
|
||||
// that the server is gracefully shut down.
|
||||
val.errGroup.Go(func() error {
|
||||
return servergrpc.StartGRPCServer(ctx, logger.With(log.ModuleKey, "grpc-server"), grpcCfg, grpcSrv)
|
||||
})
|
||||
|
||||
val.grpc = grpcSrv
|
||||
}
|
||||
|
||||
if val.APIAddress != "" {
|
||||
apiSrv := api.New(val.ClientCtx, logger.With(log.ModuleKey, "api-server"), val.grpc)
|
||||
app.RegisterAPIRoutes(apiSrv, val.AppConfig.API)
|
||||
|
||||
val.errGroup.Go(func() error {
|
||||
return apiSrv.Start(ctx, *val.AppConfig)
|
||||
})
|
||||
|
||||
val.api = apiSrv
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
|
||||
genTime := cmttime.Now()
|
||||
|
||||
for i := 0; i < cfg.NumValidators; i++ {
|
||||
cmtCfg := vals[i].Ctx.Config
|
||||
|
||||
nodeDir := filepath.Join(outputDir, vals[i].Moniker, "simd")
|
||||
gentxsDir := filepath.Join(outputDir, "gentxs")
|
||||
|
||||
cmtCfg.Moniker = vals[i].Moniker
|
||||
cmtCfg.SetRoot(nodeDir)
|
||||
|
||||
initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey)
|
||||
|
||||
genFile := cmtCfg.GenesisFile()
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(genFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig,
|
||||
cmtCfg, initCfg, appGenesis,
|
||||
banktypes.GenesisBalancesIterator{},
|
||||
genutiltypes.DefaultMessageValidator,
|
||||
cfg.TxConfig.SigningContext().ValidatorAddressCodec(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// overwrite each validator's genesis file to have a canonical genesis time
|
||||
if err := genutil.ExportGenesisFileWithTime(genFile, cfg.ChainID, nil, appState, genTime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string) error {
|
||||
// set the accounts in the genesis state
|
||||
var authGenState authtypes.GenesisState
|
||||
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState)
|
||||
|
||||
accounts, err := authtypes.PackAccounts(genAccounts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authGenState.Accounts = append(authGenState.Accounts, accounts...)
|
||||
cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState)
|
||||
|
||||
// set the balances in the genesis state
|
||||
var bankGenState banktypes.GenesisState
|
||||
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &bankGenState)
|
||||
|
||||
bankGenState.Balances = append(bankGenState.Balances, genBalances...)
|
||||
cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState)
|
||||
|
||||
appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appGenesis := genutiltypes.AppGenesis{
|
||||
ChainID: cfg.ChainID,
|
||||
AppState: appGenStateJSON,
|
||||
Consensus: &genutiltypes.ConsensusGenesis{
|
||||
Validators: nil,
|
||||
},
|
||||
}
|
||||
|
||||
// generate empty genesis files for each validator and save
|
||||
for i := 0; i < cfg.NumValidators; i++ {
|
||||
if err := appGenesis.SaveAs(genFiles[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeFile(name, dir string, contents []byte) error {
|
||||
file := filepath.Join(dir, name)
|
||||
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return fmt.Errorf("could not create directory %q: %w", dir, err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(file, contents, 0o600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get a free address for a test CometBFT server
|
||||
// protocol is either tcp, http, etc
|
||||
func FreeTCPAddr() (addr, port string, closeFn func() error, err error) {
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
|
||||
closeFn = func() error {
|
||||
return l.Close()
|
||||
}
|
||||
|
||||
portI := l.Addr().(*net.TCPAddr).Port
|
||||
port = fmt.Sprintf("%d", portI)
|
||||
addr = fmt.Sprintf("tcp://0.0.0.0:%s", port)
|
||||
return
|
||||
}
|
||||
53
utils/address.go
Normal file
53
utils/address.go
Normal file
@ -0,0 +1,53 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"cosmossdk.io/core/address"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
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 NewValAddressCodec() address.ValidatorAddressCodec {
|
||||
return addressCodec{
|
||||
Codec: addresscodec.NewBech32Codec(params.Bech32PrefixValAddr),
|
||||
}
|
||||
}
|
||||
|
||||
func NewConsAddressCodec() address.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
|
||||
}
|
||||
@ -3,12 +3,15 @@ package utils
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/core/gas"
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
const RefundModuleGasDescriptor = "laconic module gas refund"
|
||||
|
||||
func CtxWithCustomKVGasConfig(ctx *sdk.Context) *sdk.Context {
|
||||
updatedCtx := ctx.WithKVGasConfig(storetypes.GasConfig{
|
||||
HasCost: 0,
|
||||
@ -23,7 +26,16 @@ func CtxWithCustomKVGasConfig(ctx *sdk.Context) *sdk.Context {
|
||||
return &updatedCtx
|
||||
}
|
||||
|
||||
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.Consumed()
|
||||
logger.Info("tx executed", "method", method, "gas_consumed", fmt.Sprintf("%d", gasConsumed))
|
||||
}
|
||||
|
||||
func TrackGasConsumption(meter gas.Meter) func(log.Logger, string) {
|
||||
startGas := meter.Consumed()
|
||||
return func(logger log.Logger, method string) {
|
||||
endGas := meter.Consumed()
|
||||
meter.Refund(endGas-startGas, RefundModuleGasDescriptor)
|
||||
LogTxGasConsumed(meter, logger, method)
|
||||
}
|
||||
}
|
||||
|
||||
28
utils/keys.go
Normal file
28
utils/keys.go
Normal file
@ -0,0 +1,28 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
// cosmos-sdk crypto/keyring/record.go:138
|
||||
func extractPrivKeyFromLocal(rl *keyring.Record_Local) (cryptotypes.PrivKey, error) {
|
||||
if rl.PrivKey == nil {
|
||||
return nil, keyring.ErrPrivKeyNotAvailable
|
||||
}
|
||||
|
||||
priv, ok := rl.PrivKey.GetCachedValue().(cryptotypes.PrivKey)
|
||||
if !ok {
|
||||
return nil, errorsmod.Wrap(keyring.ErrCastAny, "PrivKey")
|
||||
}
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
func ExtractPrivateKey(kr keyring.Keyring, uid string) (cryptotypes.PrivKey, error) {
|
||||
ethkr, err := kr.Key(uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return extractPrivKeyFromLocal(ethkr.GetLocal())
|
||||
}
|
||||
38
utils/modules.go
Normal file
38
utils/modules.go
Normal file
@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"cosmossdk.io/core/address"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
govtypes "cosmossdk.io/x/gov/types"
|
||||
"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"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
@ -2,17 +2,33 @@ 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 ethereumAddress.String(), err
|
||||
return crypto.RecoverEthMessageSignerAddress(message, signature)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user