diff --git a/Makefile b/Makefile index 1dc426e4..4a1dd112 100644 --- a/Makefile +++ b/Makefile @@ -97,6 +97,8 @@ COVERAGE_DIR := coverage # that are not part of the first-party test suite). USER_GNO_PKGS := $(patsubst %/gnomod.toml,./%/,$(shell find gno.land/p/onbloc gno.land/r/onbloc -name gnomod.toml | grep -v '/ignore/' | sort)) TEST_GNO_PKGS := $(if $(PKG),$(addprefix ./,$(patsubst ./%,%,$(PKG))),$(USER_GNO_PKGS)) +SCENARIO_GNO_PKGS := $(patsubst %/gnomod.toml,./%/,$(shell find gno.land/r/onbloc/ibc/scenario -name gnomod.toml | grep -v '/ignore/' | sort)) +SCENARIO_TEST_GNO_PKGS := $(if $(PKG),$(addprefix ./,$(patsubst ./%,%,$(PKG))),$(SCENARIO_GNO_PKGS)) GNO_TEST_FLAGS := -v$(if $(RUN), -run "$(RUN)") help: @@ -186,6 +188,12 @@ test: verify-gno vendor gno test $(GNO_TEST_FLAGS) "$$pkg" || exit $$?; \ done +test-scenario: verify-gno vendor + @for pkg in $(SCENARIO_TEST_GNO_PKGS); do \ + echo "==> gno test $(GNO_TEST_FLAGS) $$pkg"; \ + gno test $(GNO_TEST_FLAGS) "$$pkg" || exit $$?; \ + done + test-smoke: verify-gno @gno test ./gno.land/p/core/_smoke/ -v diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/fixtures.gno b/gno.land/r/onbloc/ibc/scenario/helper/realcometbls/fixtures.gno similarity index 100% rename from gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/fixtures.gno rename to gno.land/r/onbloc/ibc/scenario/helper/realcometbls/fixtures.gno diff --git a/gno.land/r/onbloc/ibc/scenario/helper/realcometbls/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/helper/realcometbls/gnomod.toml new file mode 100644 index 00000000..b1ed2535 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/helper/realcometbls/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/helper/realcometbls" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/setup.gno b/gno.land/r/onbloc/ibc/scenario/helper/realcometbls/setup.gno similarity index 94% rename from gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/setup.gno rename to gno.land/r/onbloc/ibc/scenario/helper/realcometbls/setup.gno index 7b6f7d53..df059265 100644 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/setup.gno +++ b/gno.land/r/onbloc/ibc/scenario/helper/realcometbls/setup.gno @@ -123,9 +123,12 @@ func openZ35Channel(cur realm, connectionId types.ConnectionId, counterpartyChan } func BatchSend(cur realm, packet types.Packet) types.H256 { - stdtesting.SetRealm(stdtesting.NewCodeRealm(zkgm.ProductionImplPath())) + // The current model installs the v1 impl under this path; core.BatchSend is + // relayer-gated, so the caller must hold RELAYER (the rewritten filetests grant + // it to the admin before invoking BatchSend through this helper). + stdtesting.SetRealm(stdtesting.NewCodeRealm("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1")) core.BatchSend(cross(cur), types.NewMsgBatchSend([]types.Packet{packet})) - stdtesting.SetRealm(stdtesting.NewCodeRealm("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls")) + stdtesting.SetRealm(stdtesting.NewCodeRealm("gno.land/r/onbloc/ibc/scenario/helper/realcometbls")) return types.MustCommit(types.CommitPackets([]types.Packet{packet})) } diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/attacker.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/attacker.gno deleted file mode 100644 index a3713675..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/attacker.gno +++ /dev/null @@ -1,95 +0,0 @@ -package attacker - -import ( - app "gno.land/p/onbloc/ibc/union/app" - - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const forgedDestinationChannel = types.ChannelId(5) - -func init(cur realm) { - impl.Register(cross(cur)) -} - -func AppRecvForgedInitialize(cur realm) types.RecvPacketResult { - return zkgm.AsIBCApp().OnRecvPacket(cross(cur), forgedInitializePacket(cross(cur)), address(testutils.TestAddress("forged-relayer")), nil) -} - -func AppIntentRecvForgedInitialize(cur realm) types.RecvPacketResult { - return zkgm.AsIBCApp().(app.IIntentApp).OnIntentRecvPacket(cross(cur), forgedInitializePacket(cross(cur)), address(testutils.TestAddress("forged-maker")), nil) -} - -func AppAckForgedInitialize(cur realm) { - zkgm.AsIBCApp().OnAcknowledgementPacket(cross(cur), forgedInitializePacket(cross(cur)), []byte("ack"), address(testutils.TestAddress("forged-relayer"))) -} - -func AppTimeoutForgedInitialize(cur realm) { - zkgm.AsIBCApp().OnTimeoutPacket(cross(cur), forgedInitializePacket(cross(cur)), address(testutils.TestAddress("forged-relayer"))) -} - -func ReleaseNativeDirect(cur realm) { - zkgm.ReleaseNative(cross(cur), "ugnot", testutils.TestAddress("release-recipient"), 1) -} - -func BatchSendDirect(cur realm) { - zkgm.BatchSend(cross(cur), types.NewMsgBatchSend([]types.Packet{forgedInitializePacket(cross(cur))})) -} - -func WriteForwardAckDirect(cur realm) { - zkgm.WriteForwardAck(cross(cur), forgedInitializePacket(cross(cur)), []byte("ack")) -} - -func RegisterForeignClientDirect(cur realm) { - core.RegisterClient(cross(cur), types.ClientType("cometbls"), nil) -} - -func forgedInitializePacket(cur realm) types.Packet { - meta := z.TokenMetadata{ - Implementation: []byte("grc20"), - Initializer: []byte("init"), - } - - metaBytes, err := z.EncodeTokenMetadata(meta) - if err != nil { - panic(err) - } - - ibcDenom := z.PredictWrappedTokenV2(u256.Zero(), uint32(forgedDestinationChannel), []byte("ugnot"), z.MetadataImage(meta)) - - orderBytes, err := z.EncodeTokenOrderV2(z.TokenOrderV2{ - Sender: []byte("attacker-sender"), - Receiver: []byte(testutils.TestAddress("forged-receiver")), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte(ibcDenom), - QuoteAmount: u256.NewUint(100), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: metaBytes, - }) - if err != nil { - panic(err) - } - - data, err := z.EncodeZkgmPacket(z.ZkgmPacket{ - Salt: [32]byte{}, - Path: u256.Zero(), - Instruction: z.Instruction{ - Version: z.INSTR_VERSION_0, - Opcode: z.OP_TOKEN_ORDER, - Operand: orderBytes, - }, - }) - if err != nil { - panic(err) - } - - return core.NewPacket(types.ChannelId(1), forgedDestinationChannel, data, 1000) -} diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/gnomod.toml deleted file mode 100644 index e6f17cd2..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/attacker" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/recv_auth_test.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/recv_auth_test.gno deleted file mode 100644 index bd19164d..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/attacker/recv_auth_test.gno +++ /dev/null @@ -1,43 +0,0 @@ -package attacker - -import ( - "testing" - - "gno.land/p/nt/uassert/v0" -) - -func TestAppRecvRejectsExternalForgedPacket(cur realm, t *testing.T) { - uassert.AbortsContains(t, cur, "only core can recv", func() { - AppRecvForgedInitialize(cur) - }) -} - -func TestAppCallbacksRejectExternalCalls(cur realm, t *testing.T) { - uassert.AbortsContains(t, cur, "only core can intent recv", func() { - AppIntentRecvForgedInitialize(cur) - }) - uassert.AbortsContains(t, cur, "only core can ack", func() { - AppAckForgedInitialize(cur) - }) - uassert.AbortsContains(t, cur, "only core can timeout", func() { - AppTimeoutForgedInitialize(cur) - }) -} - -func TestProxyMutatorsRejectExternalCalls(cur realm, t *testing.T) { - uassert.AbortsContains(t, cur, "is not an authorized impl for release native", func() { - ReleaseNativeDirect(cur) - }) - uassert.AbortsContains(t, cur, "is not an authorized impl for batch send", func() { - BatchSendDirect(cur) - }) - uassert.AbortsContains(t, cur, "is not an authorized impl for write forward ack", func() { - WriteForwardAckDirect(cur) - }) -} - -func TestRegisterClientRejectsForeignNamespace(cur realm, t *testing.T) { - uassert.AbortsContains(t, cur, "caller not authorized to register client: unauthorized", func() { - RegisterForeignClientDirect(cur) - }) -} diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/bootstrap_nil/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/bootstrap_nil/gnomod.toml deleted file mode 100644 index 60364de1..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/bootstrap_nil/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/bootstrap_nil" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/bootstrap_nil/z1_bootstrap_nil_impl_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/bootstrap_nil/z1_bootstrap_nil_impl_filetest.gno deleted file mode 100644 index 5b4a7636..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/bootstrap_nil/z1_bootstrap_nil_impl_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/bootstrap_nil -package bootstrap_nil - -import zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - -func main(cur realm) { - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), nil, []string{ - zkgm.ProxyPkgPath() + "/v0/impl", - })) -} - -// Error: -// zkgm: bootstrap UpdateImpl must install an impl diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/gnomod.toml deleted file mode 100644 index d336b470..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/helpers.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/helpers.gno deleted file mode 100644 index 2a1ed743..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/helpers.gno +++ /dev/null @@ -1,325 +0,0 @@ -package e2e - -import ( - stdtesting "testing" - - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - core "gno.land/r/onbloc/ibc/union/core" -) - -var Relayer = address("g1relayer") - -var ( - testClientSeq uint32 - testConnectionSeq uint32 -) - -func nextTestClientId() types.ClientId { - testClientSeq++ - return types.ClientId(testClientSeq) -} - -func nextTestConnectionId() types.ConnectionId { - testConnectionSeq++ - return types.ConnectionId(testConnectionSeq) -} - -func tagAckSuccessU256() *u256.Uint { return u256.Zero().SetBytes(z.TAG_ACK_SUCCESS[:]) } -func fillTypeProtocolU256() *u256.Uint { return u256.Zero().SetBytes(z.FILL_TYPE_PROTOCOL[:]) } - -type ChannelPair struct { - ClientId types.ClientId - ConnectionId types.ConnectionId - Source types.ChannelId - Destination types.ChannelId -} - -// NewChannelPair allocates a ChannelPair in this realm so cross-realm callers -// (e.g. the impl test suite) can build one without tripping the Phase 3 -// allocation guard. -func NewChannelPair(cur realm, clientId types.ClientId, connectionId types.ConnectionId, source, destination types.ChannelId) ChannelPair { - return ChannelPair{ClientId: clientId, ConnectionId: connectionId, Source: source, Destination: destination} -} - -func RegisterMockLightClient(cur realm) { - if !core.HasClient(MockClientType) { - core.RegisterClient(cross(cur), MockClientType, MockClientImpl) - } -} - -func CreateMockClient(cur realm) types.ClientId { - RegisterMockLightClient(cross(cur)) - - clientId := nextTestClientId() - - core.CreateClient(cross(cur), types.NewMsgCreateClient(MockClientType, nil, nil)) - - return clientId -} - -func OpenE2EChannel(cur realm, counterpartyChannelId types.ChannelId) types.ChannelId { - clientId := CreateMockClient(cross(cur)) - connectionId := openConnection(cur, clientId) - - return openChannel(cur, connectionId, counterpartyChannelId) -} - -func OpenE2EChannelPair(cur realm) ChannelPair { - clientId := CreateMockClient(cross(cur)) - connectionId := openConnection(cur, clientId) - - source := openChannel(cur, connectionId, types.ChannelId(2)) - destination := openChannel(cur, connectionId, source) - - return ChannelPair{ - ClientId: clientId, - ConnectionId: connectionId, - Source: source, - Destination: destination, - } -} - -func openConnection(cur realm, clientId types.ClientId) types.ConnectionId { - connectionId := nextTestConnectionId() - - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) - - return connectionId -} - -// e2eChannelSeq mirrors the core store's monotonic channel-id allocation so the -// helpers can recover the id ChannelOpenInit no longer returns. Every e2e channel -// is created through openChannel, so it stays in lockstep with the store; it -// resets with each filetest's fresh realm. -var e2eChannelSeq uint32 - -func openChannel(cur realm, connectionId types.ConnectionId, counterpartyChannelId types.ChannelId) types.ChannelId { - portId := []byte(zkgm.ProxyPkgPath()) - core.ChannelOpenInit(cross(cur), types.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1msgrelayer")) - e2eChannelSeq++ - channelId := types.ChannelId(e2eChannelSeq) - core.ChannelOpenAck(cross(cur), types.NewMsgChannelOpenAck(channelId, zkgm.Version, counterpartyChannelId, nil, 1, "g1msgrelayer")) - - return channelId -} - -func BatchSend(cur realm, packet types.Packet) types.H256 { - stdtesting.SetRealm(stdtesting.NewCodeRealm(zkgm.ProductionImplPath())) - core.BatchSend(cross(cur), types.NewMsgBatchSend([]types.Packet{packet})) - stdtesting.SetRealm(stdtesting.NewCodeRealm("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e")) - - return types.MustCommit(types.CommitPackets([]types.Packet{packet})) -} - -func MustTokenOrderInstruction(cur realm, order z.TokenOrderV2) z.Instruction { - orderBytes, err := z.EncodeTokenOrderV2(order) - if err != nil { - panic(err) - } - - return z.Instruction{ - Version: z.INSTR_VERSION_2, - Opcode: z.OP_TOKEN_ORDER, - Operand: orderBytes, - } -} - -func MustCallInstruction(cur realm, call z.Call) z.Instruction { - callBytes, err := z.EncodeCall(call) - if err != nil { - panic(err) - } - - return z.Instruction{ - Version: z.INSTR_VERSION_0, - Opcode: z.OP_CALL, - Operand: callBytes, - } -} - -func MustBatchInstruction(cur realm, batch z.Batch) z.Instruction { - batchBytes, err := z.EncodeBatch(batch) - if err != nil { - panic(err) - } - - return z.Instruction{ - Version: z.INSTR_VERSION_0, - Opcode: z.OP_BATCH, - Operand: batchBytes, - } -} - -func MustForwardInstruction(cur realm, forward z.Forward) z.Instruction { - forwardBytes, err := z.EncodeForward(forward) - if err != nil { - panic(err) - } - - return z.Instruction{ - Version: z.INSTR_VERSION_0, - Opcode: z.OP_FORWARD, - Operand: forwardBytes, - } -} - -func ForwardPath(cur realm, channels ...uint32) *u256.Uint { - path := u256.Zero() - - for _, channel := range channels { - var err error - - path, err = z.UpdateChannelPath(path, channel) - if err != nil { - panic(err) - } - } - - return path -} - -func MustForwardChildPacket(cur realm, packet types.Packet, path *u256.Uint, parentSalt [32]byte, forward z.Forward) types.Packet { - forwardPath := mustCloneUint(forward.Path) - - tailPath, prevDestChannel := z.DequeueChannelFromPath(forwardPath) - if prevDestChannel == 0 { - panic("zkgm/e2e: forward missing previous destination channel") - } - - continuationPath, nextSourceChannel := z.DequeueChannelFromPath(tailPath) - if nextSourceChannel == 0 { - panic("zkgm/e2e: forward missing next source channel") - } - - if packet.DestinationChannelId != types.ChannelId(prevDestChannel) { - panic("zkgm/e2e: forward previous-destination mismatch") - } - - nextInstruction := forward.Instruction - - if !continuationPath.IsZero() { - nextForward := z.Forward{ - Path: continuationPath, - TimeoutHeight: 0, - TimeoutTimestamp: forward.TimeoutTimestamp, - Instruction: forward.Instruction, - } - nextInstruction = MustForwardInstruction(cross(cur), nextForward) - } - - intermediate, err := z.UpdateChannelPath(path, prevDestChannel) - if err != nil { - panic(err) - } - - nextPath, err := z.UpdateChannelPath(intermediate, nextSourceChannel) - if err != nil { - panic(err) - } - - childBytes, err := z.EncodeZkgmPacket(z.ZkgmPacket{ - Salt: z.DeriveForwardSalt(parentSalt), - Path: nextPath, - Instruction: nextInstruction, - }) - if err != nil { - panic(err) - } - - sourceChannelId := types.ChannelId(nextSourceChannel) - sourceChannel, err := core.GetChannel(sourceChannelId) - if err != nil { - panic(err) - } - - return core.NewPacket(sourceChannelId, sourceChannel.CounterpartyChannelId, childBytes, types.Timestamp(forward.TimeoutTimestamp)) -} - -func mustCloneUint(in *u256.Uint) *u256.Uint { - out, err := u256.FromDecimal(in.Dec()) - if err != nil { - panic(err) - } - - return out -} - -func MustPacketData(cur realm, instr z.Instruction) []byte { - packetBytes, err := z.EncodeZkgmPacket(z.ZkgmPacket{ - Path: u256.Zero(), - Instruction: instr, - }) - if err != nil { - panic(err) - } - - return packetBytes -} - -func MustTokenMetadata(cur realm, implementation string, ti z.TokenInitializer) []byte { - initBytes, err := z.EncodeTokenInitializer(ti) - if err != nil { - panic(err) - } - - meta, err := z.EncodeTokenMetadata(z.TokenMetadata{ - Implementation: []byte(implementation), - Initializer: initBytes, - }) - if err != nil { - panic(err) - } - - return meta -} - -func MustAck(cur realm, tag *u256.Uint, inner []byte) []byte { - ack, err := z.EncodeAck(z.Ack{Tag: tag, InnerAck: inner}) - if err != nil { - panic(err) - } - - return ack -} - -func MustProtocolTokenOrderAck(cur realm) []byte { - bz, err := z.EncodeTokenOrderAck(z.TokenOrderAck{ - FillType: fillTypeProtocolU256(), - }) - if err != nil { - panic(err) - } - - return bz -} - -func MustSuccessAck(cur realm, inner []byte) []byte { - return MustAck(cross(cur), tagAckSuccessU256(), inner) -} - -func MustSuccessAckBytes(cur realm, inner []byte) []byte { - ack, err := z.EncodeAck(z.Ack{Tag: tagAckSuccessU256(), InnerAck: inner}) - if err != nil { - panic(err) - } - - return ack -} - -func MustCallAck(cur realm) []byte { - return MustSuccessAckBytes(cross(cur), []byte{}) -} - -func MustBatchAck(cur realm, childAcks [][]byte) []byte { - batchAck, err := z.EncodeBatchAck(z.BatchAck{Acknowledgements: childAcks}) - if err != nil { - panic(err) - } - - return MustSuccessAckBytes(cross(cur), batchAck) -} diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/mock_lc.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/mock_lc.gno deleted file mode 100644 index 41323ab1..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/mock_lc.gno +++ /dev/null @@ -1,62 +0,0 @@ -package e2e - -import ( - "errors" - - "gno.land/p/onbloc/ibc/union/lightclient" - types "gno.land/p/onbloc/ibc/union/types" -) - -const MockClientType = types.ClientType("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/mock") - -type MockLightClient struct{} - -var _ lightclient.ClientImpl = MockClientImpl - -func MockClientImpl(_, _ []byte) (lightclient.Interface, error) { - return &MockLightClient{}, nil -} - -func (m *MockLightClient) VerifyMembership(uint64, []byte, []byte, []byte) error { - return nil -} - -func (m *MockLightClient) VerifyNonMembership(uint64, []byte, []byte) error { - return nil -} - -func (m *MockLightClient) GetTimestamp() types.Timestamp { - return types.Timestamp(1) -} - -func (m *MockLightClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { - return types.Timestamp(1), nil -} - -func (m *MockLightClient) GetLatestHeight() uint64 { - return 1 -} - -func (m *MockLightClient) GetCounterpartyChainID() string { - return "mock-chain" -} - -func (m *MockLightClient) Status() lightclient.Status { - return lightclient.Active -} - -func (m *MockLightClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { - return types.StateUpdate{ - Height: 1, - ClientStateBytes: header, - ConsensusStateBytes: header, - }, nil -} - -func (m *MockLightClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { - return types.ClientCreationResult{}, nil -} - -func (m *MockLightClient) Misbehaviour(address, []byte, address) ([]byte, error) { - return nil, errors.New("mock: misbehaviour unsupported") -} diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/doc.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/doc.gno deleted file mode 100644 index 5cdd6aff..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/doc.gno +++ /dev/null @@ -1,4 +0,0 @@ -// Package scenarios holds end-to-end filetests that exercise the v1 ZKGM -// app against the mock light client. Each `z*_filetest.gno` is an -// independent `package main` program. -package scenarios diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/gnomod.toml deleted file mode 100644 index cc8d5548..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z22_v1_recv_packet_dispatches_token_order_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z22_v1_recv_packet_dispatches_token_order_filetest.gno deleted file mode 100644 index b6a915e0..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z22_v1_recv_packet_dispatches_token_order_filetest.gno +++ /dev/null @@ -1,41 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - receiver := string(testutils.TestAddress("receiver")) - quoteToken := z.PredictWrappedToken(u256.Zero(), uint32(pair.Destination), []byte("ugnot")) - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), 0) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) - - println("quote_balance", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("relayer_balance", impl.VoucherBalanceOf(quoteToken, cur.Address())) -} - -// Output: -// quote_balance 21 -// relayer_balance 79 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z24_v1_recv_batch_token_order_and_call_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z24_v1_recv_batch_token_order_and_call_filetest.gno deleted file mode 100644 index ee92b8dd..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z24_v1_recv_batch_token_order_and_call_filetest.gno +++ /dev/null @@ -1,62 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func main(cur realm) { - impl.Register(cross(cur)) - mock.Reset(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - receiver := string(testutils.TestAddress("receiver")) - quoteToken := z.PredictWrappedToken(u256.Zero(), uint32(pair.Destination), []byte("ugnot")) - - batch := z.Batch{Instructions: []z.Instruction{ - e2e.MustTokenOrderInstruction(cross(cur), z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - }), - e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(mockReceiverPath), - ContractCalldata: []byte("post-transfer-action"), - }), - }} - packet := core.NewPacket(pair.Source, pair.Destination, - e2e.MustPacketData(cross(cur), e2e.MustBatchInstruction(cross(cur), batch)), 0) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) - - println("quote_balance", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("mock_calls", mock.Calls(cross(cur))) - println("last_calldata", mock.LastCalldata(cross(cur))) - println("receipt_after_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_recv", core.HasAcknowledgement(cross(cur), packet)) - println("recv_batch_token_order_and_call", "ok") -} - -// Output: -// quote_balance 21 -// mock_calls 1 -// last_calldata post-transfer-action -// receipt_after_recv true -// ack_after_recv true -// recv_batch_token_order_and_call ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z27_intent_recv_call_misdispatch_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z27_intent_recv_call_misdispatch_filetest.gno deleted file mode 100644 index 540c49be..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/z27_intent_recv_call_misdispatch_filetest.gno +++ /dev/null @@ -1,74 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios -package scenarios - -// Regression for a forged OP_CALL being dispatched to the proven OnZkgm handler -// through intent recv without membership proof. -// -// A forged OP_CALL is delivered through the proofless market-maker fast path -// core.IntentPacketRecv, which performs no VerifyMembership. Intent calls must -// fail closed with ACK_ERR_ONLY_MAKER so IntentRecv reverts and the call waits -// for proven recv. -// -// The mock's OnZkgm increments Calls and records calldata. This test asserts -// that bare OP_CALL and batched OP_CALL both revert before reaching OnZkgm. - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func intentRecvReverted(cur realm, packet types.Packet) (reverted bool) { - p := revive(func() { - core.IntentPacketRecv(cross(cur), - types.NewMsgIntentPacketRecv([]types.Packet{packet}, [][]byte{nil})) - }) - return p != nil -} - -func main(cur realm) { - impl.Register(cross(cur)) - mock.Reset(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - // 1. A bare forged OP_CALL with no membership proof. - call := z.Call{ - Sender: []byte("attacker-sender"), - ContractAddress: []byte(mockReceiverPath), - ContractCalldata: []byte("forged-no-proof"), - } - callPacket := core.NewPacket(pair.Source, pair.Destination, - e2e.MustPacketData(cross(cur), e2e.MustCallInstruction(cross(cur), call)), types.Timestamp(0)) - - println("call_reverted", intentRecvReverted(cur, callPacket)) - println("call_mock_calls", mock.Calls(cross(cur))) - - // 2. The same hole via an OP_BATCH child call (batch on intent reuses - // executeCall), to confirm the acceptance criterion about batched calls. - mock.Reset(cross(cur)) - batch := z.Batch{Instructions: []z.Instruction{ - e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("attacker-sender"), - ContractAddress: []byte(mockReceiverPath), - ContractCalldata: []byte("forged-batch-call"), - }), - }} - batchPacket := core.NewPacket(pair.Source, pair.Destination, - e2e.MustPacketData(cross(cur), e2e.MustBatchInstruction(cross(cur), batch)), types.Timestamp(0)) - - println("batch_reverted", intentRecvReverted(cur, batchPacket)) - println("batch_mock_calls", mock.Calls(cross(cur))) -} - -// Output: -// call_reverted true -// call_mock_calls 0 -// batch_reverted true -// batch_mock_calls 0 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/zs87_salt_dedup_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/zs87_salt_dedup_filetest.gno deleted file mode 100644 index 18be96c9..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios/zs87_salt_dedup_filetest.gno +++ /dev/null @@ -1,113 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - receiver := string(testutils.TestAddress("zs87-receiver")) - metaBytes := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Dedup Token", Symbol: "DDP", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(pair.Destination), []byte("ugnot"), z.MetadataImage(mustDecodeZS87TokenMetadata(metaBytes))) - order := z.TokenOrderV2{ - Sender: []byte("same-sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(10), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(10), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: metaBytes, - } - otherMetaBytes := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Other Dedup Token", Symbol: "DDP2", Decimals: 6}) - otherQuoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(pair.Destination), []byte("uother"), z.MetadataImage(mustDecodeZS87TokenMetadata(otherMetaBytes))) - otherOrder := z.TokenOrderV2{ - Sender: []byte("same-sender"), - Receiver: []byte(receiver), - BaseToken: []byte("uother"), - BaseAmount: u256.NewUint(10), - QuoteToken: []byte(otherQuoteToken), - QuoteAmount: u256.NewUint(10), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: otherMetaBytes, - } - - var saltA [32]byte - saltA[31] = 1 - var saltB [32]byte - saltB[31] = 2 - derivedA := z.DeriveSenderSalt(order.Sender, saltA) - derivedA2 := z.DeriveSenderSalt(order.Sender, saltA) - derivedB := z.DeriveSenderSalt(order.Sender, saltB) - println("same_sender_salt_equal", derivedA == derivedA2) - println("different_salt_distinct", derivedA != derivedB) - - samePacket := core.NewPacket(pair.Source, pair.Destination, - mustSaltedPacketData(cross(cur), derivedA, e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(1<<62)) - samePacket2 := core.NewPacket(pair.Source, pair.Destination, - mustSaltedPacketData(cross(cur), derivedA2, e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(1<<62)) - otherPacket := core.NewPacket(pair.Source, pair.Destination, - mustSaltedPacketData(cross(cur), derivedB, e2e.MustTokenOrderInstruction(cross(cur), otherOrder)), types.Timestamp(1<<62)) - println("same_packet_commit_equal", types.MustCommit(types.CommitPacket(samePacket)) == types.MustCommit(types.CommitPacket(samePacket2))) - println("different_salt_commit_distinct", types.MustCommit(types.CommitPacket(samePacket)) != types.MustCommit(types.CommitPacket(otherPacket))) - - println("") - println("[SCENARIO] repeated packet is swallowed by receipt") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{samePacket}, [][]byte{nil}, nil, 1)) - println("receipt_after_first", core.HasPacketReceipt(cross(cur), samePacket)) - println("receiver_after_first", impl.VoucherBalanceOf(quoteToken, address(receiver))) - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{samePacket}, [][]byte{nil}, nil, 1)) - println("receiver_after_second_same", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] different salt is a distinct packet") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{otherPacket}, [][]byte{nil}, nil, 1)) - println("other_receipt", core.HasPacketReceipt(cross(cur), otherPacket)) - println("receiver_other_token", impl.VoucherBalanceOf(otherQuoteToken, address(receiver))) -} - -func mustSaltedPacketData(cur realm, salt [32]byte, instr z.Instruction) []byte { - packetBytes, err := z.EncodeZkgmPacket(z.ZkgmPacket{ - Salt: salt, - Path: u256.Zero(), - Instruction: instr, - }) - if err != nil { - panic(err) - } - return packetBytes -} - -func mustDecodeZS87TokenMetadata(bz []byte) z.TokenMetadata { - meta, err := z.DecodeTokenMetadata(bz) - if err != nil { - panic(err) - } - return meta -} - -// Output: -// same_sender_salt_equal true -// different_salt_distinct true -// same_packet_commit_equal true -// different_salt_commit_distinct true -// -// [SCENARIO] repeated packet is swallowed by receipt -// receipt_after_first true -// receiver_after_first 10 -// receiver_after_second_same 10 -// -// [SCENARIO] different salt is a distinct packet -// other_receipt true -// receiver_other_token 10 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/gnomod.toml deleted file mode 100644 index 8fee0a07..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z21_v1_create_client_handshake_send_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z21_v1_create_client_handshake_send_filetest.gno deleted file mode 100644 index 21616490..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z21_v1_create_client_handshake_send_filetest.gno +++ /dev/null @@ -1,44 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte("receiver"), - BaseToken: []byte("ugnot"), - BaseAmount: u256.Zero(), - QuoteToken: []byte("quote"), - QuoteAmount: u256.Zero(), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}), - } - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(3600)) - e2e.BatchSend(cross(cur), packet) - - println("client", pair.ClientId.String()) - println("source_channel", pair.Source.String()) - println("destination_channel", pair.Destination.String()) - println("packet_source", packet.SourceChannelId.String()) - println("packet_destination", packet.DestinationChannelId.String()) -} - -// Output: -// client 1 -// source_channel 1 -// destination_channel 2 -// packet_source 1 -// packet_destination 2 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z23_v1_token_order_roundtrip_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z23_v1_token_order_roundtrip_filetest.gno deleted file mode 100644 index f7e888db..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z23_v1_token_order_roundtrip_filetest.gno +++ /dev/null @@ -1,56 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - sender := "g17xpfvakm2amg962yls6f84z3kell8c5lserqta" - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - metaBytes := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(pair.Destination), []byte("ugnot"), z.MetadataImage(mustDecodeTokenMetadata(metaBytes))) - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(33), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(33), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: metaBytes, - } - instr := e2e.MustTokenOrderInstruction(cross(cur), order) - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), instr), types.Timestamp(1<<62)) - e2e.BatchSend(cross(cur), packet) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) - - ack := e2e.MustSuccessAck(cross(cur), e2e.MustProtocolTokenOrderAck(cross(cur))) - core.PacketAcknowledgement(cross(cur), types.NewMsgPacketAcknowledgement([]types.Packet{packet}, [][]byte{ack}, nil, 1)) - - println("quote_balance", impl.VoucherBalanceOf(z.PredictWrappedTokenV2(u256.Zero(), uint32(pair.Destination), order.BaseToken, z.MetadataImage(mustDecodeTokenMetadata(order.Metadata))), address(receiver))) - println("ack_roundtrip", "ok") -} - -func mustDecodeTokenMetadata(bz []byte) z.TokenMetadata { - meta, err := z.DecodeTokenMetadata(bz) - if err != nil { - panic(err) - } - return meta -} - -// Output: -// quote_balance 33 -// ack_roundtrip ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z25_forward_allowedimpls_positive_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z25_forward_allowedimpls_positive_filetest.gno deleted file mode 100644 index f3a2765e..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z25_forward_allowedimpls_positive_filetest.gno +++ /dev/null @@ -1,52 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - parentChannel := e2e.OpenE2EChannel(cross(cur), types.ChannelId(101)) - childSource := e2e.OpenE2EChannel(cross(cur), types.ChannelId(102)) - - forward := z.Forward{ - Path: e2e.ForwardPath(cross(cur), uint32(parentChannel), uint32(childSource)), - TimeoutTimestamp: 999, - Instruction: e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock"), - ContractCalldata: []byte("forward-core-frame"), - }), - } - packet := core.NewPacket(types.ChannelId(1), parentChannel, - e2e.MustPacketData(cross(cur), e2e.MustForwardInstruction(cross(cur), forward)), types.Timestamp(0)) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) - - expectedChild := e2e.MustForwardChildPacket(cross(cur), packet, u256.Zero(), [32]byte{}, forward) - _, inFlight := zkgm.GetInFlightPacket(zkgm.NewInFlightKey(cross(cur), types.MustCommit(types.CommitPacket(expectedChild)))) - - println("impl_path", zkgm.ImplPath()) - println("child_source", expectedChild.SourceChannelId.String()) - println("child_destination", expectedChild.DestinationChannelId.String()) - println("in_flight", inFlight) - println("parent_ack", core.HasAcknowledgement(cross(cur), packet)) - println("forward_allowedimpls_positive", "ok") -} - -// Output: -// impl_path gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1 -// child_source 2 -// child_destination 102 -// in_flight true -// parent_ack false -// forward_allowedimpls_positive ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z26_batch_acks_event_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z26_batch_acks_event_filetest.gno deleted file mode 100644 index 059d0f37..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z26_batch_acks_event_filetest.gno +++ /dev/null @@ -1,314 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - core "gno.land/r/onbloc/ibc/union/core" -) - -const batchAcksPort = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend" - -type asyncApp struct{} - -func (a *asyncApp) OnChannelOpenInit(cur realm, connectionId types.ConnectionId, channelId types.ChannelId, version string, relayer address) { -} - -func (a *asyncApp) OnChannelOpenTry(cur realm, connectionId types.ConnectionId, channelId types.ChannelId, version string, counterpartyVersion string, relayer address) { -} - -func (a *asyncApp) OnChannelOpenAck(cur realm, channelId types.ChannelId, counterpartyChannelId types.ChannelId, counterpartyVersion string, relayer address) { -} -func (a *asyncApp) OnChannelOpenConfirm(cur realm, channelId types.ChannelId, relayer address) {} -func (a *asyncApp) OnChannelCloseInit(cur realm, channelId types.ChannelId, relayer address) {} -func (a *asyncApp) OnChannelCloseConfirm(cur realm, channelId types.ChannelId, relayer address) { -} - -func (a *asyncApp) OnRecvPacket(cur realm, packet types.Packet, relayer address, relayerMsg []byte) types.RecvPacketResult { - return core.NewRecvPacketResult(types.PacketStatusAsync, nil) -} - -func (a *asyncApp) OnAcknowledgementPacket(cur realm, packet types.Packet, acknowledgement []byte, relayer address) { -} -func (a *asyncApp) OnTimeoutPacket(cur realm, packet types.Packet, relayer address) {} - -func main(cur realm) { - e2e.RegisterMockLightClient(cross(cur)) - core.RegisterApp(cross(cur), &asyncApp{}) - - core.CreateClient(cross(cur), types.NewMsgCreateClient(e2e.MockClientType, nil, nil)) - clientId := types.ClientId(1) - connectionId := types.ConnectionId(1) - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) - core.ChannelOpenInit(cross(cur), types.NewMsgChannelOpenInit([]byte(batchAcksPort), []byte(batchAcksPort), connectionId, "async-v1", "g1msgrelayer")) - channelId := types.ChannelId(1) - core.ChannelOpenAck(cross(cur), types.NewMsgChannelOpenAck(channelId, "async-v1", types.ChannelId(101), nil, 1, "g1msgrelayer")) - - packet := core.NewPacket(types.ChannelId(99), channelId, []byte("async-packet"), types.Timestamp(1<<62)) - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) - - batchHash := types.MustCommit(types.CommitPackets([]types.Packet{packet})) - core.BatchAcks(cross(cur), types.NewMsgBatchAcks([]types.Packet{packet}, [][]byte{[]byte("ack")})) - println("batch_acks_hash", batchHash.String()) - println("batch_acks_event", "ok") -} - -// Output: -// batch_acks_hash 0xb75079c4d060e9310567dfe8825dcfbbc96c9cd0acfbb443517b61a01faf3c40 -// batch_acks_event ok - -// Events: -// [ -// { -// "type": "ClientRegistered", -// "attrs": [ -// { -// "key": "client_type", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/mock" -// }, -// { -// "key": "registrar_pkg_path", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" -// }, -// { -// "key": "admin_override", -// "value": "false" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "AppRegistered", -// "attrs": [ -// { -// "key": "port_id", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend" -// }, -// { -// "key": "registrar_pkg_path", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend" -// }, -// { -// "key": "admin_override", -// "value": "false" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "CreateClient", -// "attrs": [ -// { -// "key": "client_id", -// "value": "1" -// }, -// { -// "key": "client_type", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/mock" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "ConnectionOpenInit", -// "attrs": [ -// { -// "key": "connection_id", -// "value": "1" -// }, -// { -// "key": "client_id", -// "value": "1" -// }, -// { -// "key": "counterparty_client_id", -// "value": "99" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "ConnectionOpenAck", -// "attrs": [ -// { -// "key": "connection_id", -// "value": "1" -// }, -// { -// "key": "client_id", -// "value": "1" -// }, -// { -// "key": "counterparty_client_id", -// "value": "99" -// }, -// { -// "key": "counterparty_connection_id", -// "value": "77" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "ChannelOpenInit", -// "attrs": [ -// { -// "key": "port_id", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend" -// }, -// { -// "key": "channel_id", -// "value": "1" -// }, -// { -// "key": "counterparty_port_id", -// "value": "0x676e6f2e6c616e642f722f6f6e626c6f632f6962632f756e696f6e2f617070732f75637330335f7a6b676d2f74657374696e672f6532652f7363656e6172696f735f626174636873656e64" -// }, -// { -// "key": "connection_id", -// "value": "1" -// }, -// { -// "key": "connection_client_id", -// "value": "1" -// }, -// { -// "key": "connection_counterparty_client_id", -// "value": "99" -// }, -// { -// "key": "connection_counterparty_connection_id", -// "value": "77" -// }, -// { -// "key": "version", -// "value": "async-v1" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "ChannelOpenAck", -// "attrs": [ -// { -// "key": "port_id", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend" -// }, -// { -// "key": "channel_id", -// "value": "1" -// }, -// { -// "key": "counterparty_port_id", -// "value": "0x676e6f2e6c616e642f722f6f6e626c6f632f6962632f756e696f6e2f617070732f75637330335f7a6b676d2f74657374696e672f6532652f7363656e6172696f735f626174636873656e64" -// }, -// { -// "key": "counterparty_channel_id", -// "value": "101" -// }, -// { -// "key": "connection_id", -// "value": "1" -// }, -// { -// "key": "connection_client_id", -// "value": "1" -// }, -// { -// "key": "connection_counterparty_client_id", -// "value": "99" -// }, -// { -// "key": "connection_counterparty_connection_id", -// "value": "77" -// }, -// { -// "key": "version", -// "value": "async-v1" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "PacketRecv", -// "attrs": [ -// { -// "key": "packet_hash", -// "value": "0xb75079c4d060e9310567dfe8825dcfbbc96c9cd0acfbb443517b61a01faf3c40" -// }, -// { -// "key": "packet_data", -// "value": "0x6173796e632d7061636b6574" -// }, -// { -// "key": "source_channel_id", -// "value": "99" -// }, -// { -// "key": "source_connection_id", -// "value": "77" -// }, -// { -// "key": "source_connection_client_id", -// "value": "99" -// }, -// { -// "key": "destination_channel_id", -// "value": "1" -// }, -// { -// "key": "destination_channel_version", -// "value": "async-v1" -// }, -// { -// "key": "destination_connection_id", -// "value": "1" -// }, -// { -// "key": "destination_connection_client_id", -// "value": "1" -// }, -// { -// "key": "timeout_timestamp", -// "value": "4611686018427387904" -// }, -// { -// "key": "maker_msg", -// "value": "0x" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// }, -// { -// "type": "BatchAcks", -// "attrs": [ -// { -// "key": "batch_hash", -// "value": "0xb75079c4d060e9310567dfe8825dcfbbc96c9cd0acfbb443517b61a01faf3c40" -// }, -// { -// "key": "ack_hash", -// "value": "0x01644e63d4e00fb98df51e358ca223c9095b3e27fe19de5647969de2d9f056bd" -// }, -// { -// "key": "destination_channel_id", -// "value": "1" -// }, -// { -// "key": "destination_channel_version", -// "value": "async-v1" -// }, -// { -// "key": "destination_connection_id", -// "value": "1" -// }, -// { -// "key": "destination_connection_client_id", -// "value": "1" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/core" -// } -// ] diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z41_forward_multihop_roundtrip_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z41_forward_multihop_roundtrip_filetest.gno deleted file mode 100644 index e2010b45..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/z41_forward_multihop_roundtrip_filetest.gno +++ /dev/null @@ -1,74 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - - z "gno.land/p/onbloc/ibc/union/zkgm" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - "gno.land/r/onbloc/ibc/union/core" - - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - parentChannel := e2e.OpenE2EChannel(cross(cur), types.ChannelId(101)) - childSource := e2e.OpenE2EChannel(cross(cur), types.ChannelId(102)) - - forward := z.Forward{ - Path: e2e.ForwardPath(cross(cur), uint32(parentChannel), uint32(childSource)), - TimeoutTimestamp: 999, - Instruction: e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock"), - ContractCalldata: []byte("forward-roundtrip"), - }), - } - parent := core.NewPacket(parentChannel, parentChannel, - e2e.MustPacketData(cross(cur), e2e.MustForwardInstruction(cross(cur), forward)), types.Timestamp(0)) - child := e2e.MustForwardChildPacket(cross(cur), parent, u256.Zero(), [32]byte{}, forward) - childKey := zkgm.NewInFlightKey(cross(cur), types.MustCommit(types.CommitPacket(child))) - - println("[SCENARIO] 1. forward recv creates child and defers parent ack") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{parent}, [][]byte{nil}, nil, 1)) - _, inFlight := zkgm.GetInFlightPacket(childKey) - println("impl_path", zkgm.ImplPath()) - println("child_source", child.SourceChannelId.String()) - println("child_destination", child.DestinationChannelId.String()) - println("child_commitment_before_ack", core.HasPacketCommitment(cross(cur), child)) - println("in_flight_before_ack", inFlight) - println("parent_ack_before_ack", core.HasAcknowledgement(cross(cur), parent)) - - println("") - println("[SCENARIO] 2. child ack propagates to parent") - childAck := e2e.MustCallAck(cross(cur)) - core.PacketAcknowledgement(cross(cur), types.NewMsgPacketAcknowledgement([]types.Packet{child}, [][]byte{childAck}, nil, 1)) - _, inFlight = zkgm.GetInFlightPacket(childKey) - println("child_commitment_after_ack", core.HasPacketCommitment(cross(cur), child)) - println("in_flight_after_ack", inFlight) - println("parent_ack_after_ack", core.HasAcknowledgement(cross(cur), parent)) - println("parent_ack_matches_child_ack", core.AcknowledgementHash(cross(cur), parent).String() == types.CommitAcks([][]byte{childAck}).String()) - println("forward_multihop_roundtrip", "ok") -} - -// Output: -// [SCENARIO] 1. forward recv creates child and defers parent ack -// impl_path gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1 -// child_source 2 -// child_destination 102 -// child_commitment_before_ack true -// in_flight_before_ack true -// parent_ack_before_ack false -// -// [SCENARIO] 2. child ack propagates to parent -// child_commitment_after_ack false -// in_flight_after_ack false -// parent_ack_after_ack true -// parent_ack_matches_child_ack true -// forward_multihop_roundtrip ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs11_handshake_send_recv_ack_success_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs11_handshake_send_recv_ack_success_filetest.gno deleted file mode 100644 index 68ffe725..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs11_handshake_send_recv_ack_success_filetest.gno +++ /dev/null @@ -1,72 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - quoteToken := z.PredictWrappedToken(u256.Zero(), uint32(pair.Destination), []byte("ugnot")) - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(1<<62)) - - // BatchSend commits the packet directly, so this file covers the core - // lifecycle flags and recv-side mint. Send-side escrow is covered elsewhere. - println("[SCENARIO] 1. open channel and commit packet") - e2e.BatchSend(cross(cur), packet) - println("source_channel", packet.SourceChannelId.String()) - println("destination_channel", packet.DestinationChannelId.String()) - println("commitment_after_send", core.HasPacketCommitment(cross(cur), packet)) - println("receipt_before_recv", core.HasPacketReceipt(cross(cur), packet)) - - println("") - println("[SCENARIO] 2. recv success") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) - println("receipt_after_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_recv", core.HasAcknowledgement(cross(cur), packet)) - println("quote_balance_after_recv", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] 3. ack success") - ack := e2e.MustSuccessAck(cross(cur), e2e.MustProtocolTokenOrderAck(cross(cur))) - core.PacketAcknowledgement(cross(cur), types.NewMsgPacketAcknowledgement([]types.Packet{packet}, [][]byte{ack}, nil, 1)) - println("commitment_after_ack", core.HasPacketCommitment(cross(cur), packet)) - println("receipt_after_ack", core.HasPacketReceipt(cross(cur), packet)) - println("ack_success_roundtrip", "ok") -} - -// Output: -// [SCENARIO] 1. open channel and commit packet -// source_channel 1 -// destination_channel 2 -// commitment_after_send true -// receipt_before_recv false -// -// [SCENARIO] 2. recv success -// receipt_after_recv true -// ack_after_recv true -// quote_balance_after_recv 21 -// -// [SCENARIO] 3. ack success -// commitment_after_ack false -// receipt_after_ack true -// ack_success_roundtrip ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs13_initialize_escrow_voucher_lifecycle_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs13_initialize_escrow_voucher_lifecycle_filetest.gno deleted file mode 100644 index 5d1d1c03..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs13_initialize_escrow_voucher_lifecycle_filetest.gno +++ /dev/null @@ -1,78 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - metaBytes := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(pair.Destination), []byte("ugnot"), z.MetadataImage(mustDecodeTokenMetadata(metaBytes))) - - initialize := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(33), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(33), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: metaBytes, - } - initPacket := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), initialize)), types.Timestamp(1<<62)) - println("[SCENARIO] 1. initialize voucher") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{initPacket}, [][]byte{nil}, nil, 1)) - _, hasOriginAfterInitialize := zkgm.GetTokenOrigin(quoteToken) - println("voucher_balance_after_initialize", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("origin_after_initialize", hasOriginAfterInitialize) - println("initialize_receipt", core.HasPacketReceipt(cross(cur), initPacket)) - - println("") - escrow := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - escrowPacket := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), escrow)), types.Timestamp(1<<62)) - println("[SCENARIO] 2. escrow into existing voucher") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{escrowPacket}, [][]byte{nil}, nil, 1)) - _, hasOriginAfterEscrow := zkgm.GetTokenOrigin(quoteToken) - println("voucher_balance_after_escrow", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("origin_after_escrow", hasOriginAfterEscrow) - println("escrow_receipt", core.HasPacketReceipt(cross(cur), escrowPacket)) -} - -func mustDecodeTokenMetadata(bz []byte) z.TokenMetadata { - meta, err := z.DecodeTokenMetadata(bz) - if err != nil { - panic(err) - } - return meta -} - -// Output: -// [SCENARIO] 1. initialize voucher -// voucher_balance_after_initialize 33 -// origin_after_initialize true -// initialize_receipt true -// -// [SCENARIO] 2. escrow into existing voucher -// voucher_balance_after_escrow 54 -// origin_after_escrow true -// escrow_receipt true diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs14a_duplicate_success_recv_noop_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs14a_duplicate_success_recv_noop_filetest.gno deleted file mode 100644 index 34418fe0..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs14a_duplicate_success_recv_noop_filetest.gno +++ /dev/null @@ -1,61 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - quoteToken := z.PredictWrappedToken(u256.Zero(), uint32(pair.Destination), []byte("ugnot")) - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(1<<62)) - msg := types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1) - - println("quote_balance_before_recv", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("[SCENARIO] 1. first recv mints") - core.PacketRecv(cross(cur), msg) - println("receipt_after_first_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_first_recv", core.HasAcknowledgement(cross(cur), packet)) - println("quote_balance_after_first_recv", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] 2. duplicate recv is skipped") - core.PacketRecv(cross(cur), msg) - println("receipt_after_second_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_second_recv", core.HasAcknowledgement(cross(cur), packet)) - println("quote_balance_after_second_recv", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("duplicate_success_recv_noop", "ok") -} - -// Output: -// quote_balance_before_recv 0 -// [SCENARIO] 1. first recv mints -// receipt_after_first_recv true -// ack_after_first_recv true -// quote_balance_after_first_recv 21 -// -// [SCENARIO] 2. duplicate recv is skipped -// receipt_after_second_recv true -// ack_after_second_recv true -// quote_balance_after_second_recv 21 -// duplicate_success_recv_noop ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs14b_ack_timeout_noops_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs14b_ack_timeout_noops_filetest.gno deleted file mode 100644 index 1ea29fbe..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs14b_ack_timeout_noops_filetest.gno +++ /dev/null @@ -1,165 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - "errors" - - "gno.land/p/onbloc/ibc/union/lightclient" - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const timeoutScenarioClientType = types.ClientType("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend/timeout") - -type timeoutScenarioLightClient struct{} - -var _ lightclient.ClientImpl = timeoutScenarioClientImpl - -func timeoutScenarioClientImpl(_, _ []byte) (lightclient.Interface, error) { - return &timeoutScenarioLightClient{}, nil -} - -func (m *timeoutScenarioLightClient) VerifyMembership(uint64, []byte, []byte, []byte) error { - return nil -} - -func (m *timeoutScenarioLightClient) VerifyNonMembership(uint64, []byte, []byte) error { - return nil -} - -func (m *timeoutScenarioLightClient) GetTimestamp() types.Timestamp { - return types.Timestamp(2) -} - -func (m *timeoutScenarioLightClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { - return types.Timestamp(2), nil -} - -func (m *timeoutScenarioLightClient) GetLatestHeight() uint64 { - return 1 -} - -func (m *timeoutScenarioLightClient) GetCounterpartyChainID() string { - return "timeout-scenario-chain" -} - -func (m *timeoutScenarioLightClient) Status() lightclient.Status { - return lightclient.Active -} - -func (m *timeoutScenarioLightClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { - return types.StateUpdate{Height: 1, ClientStateBytes: header, ConsensusStateBytes: header}, nil -} - -func (m *timeoutScenarioLightClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { - return types.ClientCreationResult{}, nil -} - -func (m *timeoutScenarioLightClient) Misbehaviour(address, []byte, address) ([]byte, error) { - return nil, errors.New("mock: misbehaviour unsupported") -} - -func main(cur realm) { - impl.Register(cross(cur)) - pair := openTimeoutScenarioChannelPair(cross(cur)) - sender := string(testutils.TestAddress("timeout-sender")) - marketMaker := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte(marketMaker), - BaseToken: []byte("ibc/base"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(1)) - ack := e2e.MustSuccessAck(cross(cur), mustMarketMakerTokenOrderAck([]byte(marketMaker))) - ackMsg := types.NewMsgPacketAcknowledgement([]types.Packet{packet}, [][]byte{ack}, nil, 1) - - // This file exercises core idempotency only. BatchSend plants the packet - // commitment directly and intentionally bypasses the send-side voucher escrow. - println("[SCENARIO] 1. first ack settles") - e2e.BatchSend(cross(cur), packet) - core.PacketAcknowledgement(cross(cur), ackMsg) - println("commitment_after_first_ack", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_after_first_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - - println("") - println("[SCENARIO] 2. duplicate ack is skipped") - core.PacketAcknowledgement(cross(cur), ackMsg) - println("commitment_after_second_ack", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_after_second_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - - println("") - println("[SCENARIO] 3. timeout after ack is skipped") - core.PacketTimeout(cross(cur), types.NewMsgPacketTimeout(packet, nil, 1)) - println("sender_after_timeout_after_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(sender))) - - println("") - println("[SCENARIO] 4. ack after timeout is skipped") - e2e.BatchSend(cross(cur), packet) - core.PacketTimeout(cross(cur), types.NewMsgPacketTimeout(packet, nil, 1)) - println("commitment_after_timeout", core.HasPacketCommitment(cross(cur), packet)) - println("sender_after_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(sender))) - - core.PacketAcknowledgement(cross(cur), ackMsg) - println("market_maker_after_ack_after_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - println("sender_after_ack_after_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(sender))) - println("ack_timeout_noops", "ok") -} - -func openTimeoutScenarioChannelPair(cur realm) e2e.ChannelPair { - if !core.HasClient(timeoutScenarioClientType) { - core.RegisterClient(cross(cur), timeoutScenarioClientType, timeoutScenarioClientImpl) - } - core.CreateClient(cross(cur), types.NewMsgCreateClient(timeoutScenarioClientType, nil, nil)) - clientId := types.ClientId(1) - connectionId := types.ConnectionId(1) - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) - - portId := []byte(zkgm.ProxyPkgPath()) - core.ChannelOpenInit(cross(cur), types.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1msgrelayer")) - source := types.ChannelId(1) - core.ChannelOpenAck(cross(cur), types.NewMsgChannelOpenAck(source, zkgm.Version, types.ChannelId(2), nil, 1, "g1msgrelayer")) - return e2e.NewChannelPair(cross(cur), clientId, connectionId, source, types.ChannelId(2)) -} - -func mustMarketMakerTokenOrderAck(marketMaker []byte) []byte { - bz, err := z.EncodeTokenOrderAck(z.TokenOrderAck{ - FillType: new(u256.Uint).SetBytes(z.FILL_TYPE_MARKETMAKER[:]), - MarketMaker: marketMaker, - }) - if err != nil { - panic(err) - } - return bz -} - -// Output: -// [SCENARIO] 1. first ack settles -// commitment_after_first_ack false -// market_maker_after_first_ack 21 -// -// [SCENARIO] 2. duplicate ack is skipped -// commitment_after_second_ack false -// market_maker_after_second_ack 21 -// -// [SCENARIO] 3. timeout after ack is skipped -// sender_after_timeout_after_ack 0 -// -// [SCENARIO] 4. ack after timeout is skipped -// commitment_after_timeout false -// sender_after_timeout 21 -// market_maker_after_ack_after_timeout 21 -// sender_after_ack_after_timeout 21 -// ack_timeout_noops ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs54_forward_child_timeout_parent_failure_ack_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs54_forward_child_timeout_parent_failure_ack_filetest.gno deleted file mode 100644 index fddb3204..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs54_forward_child_timeout_parent_failure_ack_filetest.gno +++ /dev/null @@ -1,167 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - "errors" - - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/onbloc/ibc/union/lightclient" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const forwardChildTimeoutClientType = types.ClientType("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend/forward-child-timeout") - -type forwardChildTimeoutLightClient struct{} - -var _ lightclient.ClientImpl = forwardChildTimeoutClientImpl - -func forwardChildTimeoutClientImpl(_, _ []byte) (lightclient.Interface, error) { - return &forwardChildTimeoutLightClient{}, nil -} - -func (m *forwardChildTimeoutLightClient) VerifyMembership(uint64, []byte, []byte, []byte) error { - return nil -} - -func (m *forwardChildTimeoutLightClient) VerifyNonMembership(uint64, []byte, []byte) error { - return nil -} - -func (m *forwardChildTimeoutLightClient) GetTimestamp() types.Timestamp { - return types.Timestamp(2) -} - -func (m *forwardChildTimeoutLightClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { - return types.Timestamp(2), nil -} - -func (m *forwardChildTimeoutLightClient) GetLatestHeight() uint64 { - return 1 -} - -func (m *forwardChildTimeoutLightClient) GetCounterpartyChainID() string { - return "forward-child-timeout-chain" -} - -func (m *forwardChildTimeoutLightClient) Status() lightclient.Status { - return lightclient.Active -} - -func (m *forwardChildTimeoutLightClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { - return types.StateUpdate{Height: 1, ClientStateBytes: header, ConsensusStateBytes: header}, nil -} - -func (m *forwardChildTimeoutLightClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { - return types.ClientCreationResult{}, nil -} - -func (m *forwardChildTimeoutLightClient) Misbehaviour(address, []byte, address) ([]byte, error) { - return nil, errors.New("mock: misbehaviour unsupported") -} - -func main(cur realm) { - impl.Register(cross(cur)) - connectionId := openForwardChildTimeoutConnection(cross(cur)) - parentDestination := openForwardChildTimeoutChannel(cross(cur), connectionId, types.ChannelId(101)) - childSource := openForwardChildTimeoutChannel(cross(cur), connectionId, types.ChannelId(102)) - - forward := z.Forward{ - Path: e2e.ForwardPath(cross(cur), uint32(parentDestination), uint32(childSource)), - TimeoutTimestamp: 1, - Instruction: e2e.MustTokenOrderInstruction(cross(cur), z.TokenOrderV2{ - Sender: []byte("forward-sender"), - Receiver: []byte("forward-receiver"), - BaseToken: []byte("ibc/forward-base"), - BaseAmount: u256.NewUint(20), - QuoteToken: []byte("quote"), - QuoteAmount: u256.NewUint(20), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - }), - } - parentPacket := core.NewPacket(types.ChannelId(1), parentDestination, - e2e.MustPacketData(cross(cur), e2e.MustForwardInstruction(cross(cur), forward)), types.Timestamp(0)) - childPacket := e2e.MustForwardChildPacket(cross(cur), parentPacket, u256.Zero(), [32]byte{}, forward) - childKey := zkgm.NewInFlightKey(cross(cur), types.MustCommit(types.CommitPacket(childPacket))) - - println("[SCENARIO] 1. recv forward defers parent ack and tracks child") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{parentPacket}, [][]byte{nil}, nil, 1)) - _, inFlight := zkgm.GetInFlightPacket(childKey) - println("parent_receipt_after_recv", core.HasPacketReceipt(cross(cur), parentPacket)) - println("parent_ack_after_recv", core.HasAcknowledgement(cross(cur), parentPacket)) - println("child_commitment_after_recv", core.HasPacketCommitment(cross(cur), childPacket)) - println("child_inflight_after_recv", inFlight) - - println("") - println("[SCENARIO] 2. child timeout writes parent failure ack") - core.PacketTimeout(cross(cur), types.NewMsgPacketTimeout(childPacket, nil, 1)) - _, inFlight = zkgm.GetInFlightPacket(childKey) - println("child_commitment_after_timeout", core.HasPacketCommitment(cross(cur), childPacket)) - println("child_inflight_after_timeout", inFlight) - println("parent_ack_after_timeout", core.HasAcknowledgement(cross(cur), parentPacket)) - println("parent_ack_is_universal_error", core.AcknowledgementHash(cross(cur), parentPacket).String() == expectedUniversalErrorAckHash(cross(cur))) - ackHashAfterTimeout := core.AcknowledgementHash(cross(cur), parentPacket).String() - - println("") - println("[SCENARIO] 3. duplicate child timeout is a no-op") - core.PacketTimeout(cross(cur), types.NewMsgPacketTimeout(childPacket, nil, 1)) - _, inFlight = zkgm.GetInFlightPacket(childKey) - println("child_commitment_after_second_timeout", core.HasPacketCommitment(cross(cur), childPacket)) - println("child_inflight_after_second_timeout", inFlight) - println("parent_ack_after_second_timeout", core.HasAcknowledgement(cross(cur), parentPacket)) - println("parent_ack_hash_unchanged_after_second_timeout", core.AcknowledgementHash(cross(cur), parentPacket).String() == ackHashAfterTimeout) - println("forward_child_timeout_parent_failure_ack", "ok") -} - -func openForwardChildTimeoutConnection(cur realm) types.ConnectionId { - if !core.HasClient(forwardChildTimeoutClientType) { - core.RegisterClient(cross(cur), forwardChildTimeoutClientType, forwardChildTimeoutClientImpl) - } - core.CreateClient(cross(cur), types.NewMsgCreateClient(forwardChildTimeoutClientType, nil, nil)) - clientId := types.ClientId(1) - connectionId := types.ConnectionId(1) - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) - return connectionId -} - -func openForwardChildTimeoutChannel(cur realm, connectionId types.ConnectionId, counterpartyChannelId types.ChannelId) types.ChannelId { - portId := []byte(zkgm.ProxyPkgPath()) - core.ChannelOpenInit(cross(cur), types.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1msgrelayer")) - channelId := types.ChannelId(1) - core.ChannelOpenAck(cross(cur), types.NewMsgChannelOpenAck(channelId, zkgm.Version, counterpartyChannelId, nil, 1, "g1msgrelayer")) - return channelId -} - -func expectedUniversalErrorAckHash(cur realm) string { - ack, err := z.EncodeAck(z.Ack{Tag: u256.NewUint(0), InnerAck: []byte("UNIVERSAL_ERROR")}) - if err != nil { - panic(err) - } - return types.CommitAcks([][]byte{ack}).String() -} - -// Output: -// [SCENARIO] 1. recv forward defers parent ack and tracks child -// parent_receipt_after_recv true -// parent_ack_after_recv false -// child_commitment_after_recv true -// child_inflight_after_recv true -// -// [SCENARIO] 2. child timeout writes parent failure ack -// child_commitment_after_timeout false -// child_inflight_after_timeout false -// parent_ack_after_timeout true -// parent_ack_is_universal_error true -// -// [SCENARIO] 3. duplicate child timeout is a no-op -// child_commitment_after_second_timeout false -// child_inflight_after_second_timeout false -// parent_ack_after_second_timeout true -// parent_ack_hash_unchanged_after_second_timeout true -// forward_child_timeout_parent_failure_ack ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs89_large_batch_current_behavior_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs89_large_batch_current_behavior_filetest.gno deleted file mode 100644 index 0c28639a..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_batchsend/zs89_large_batch_current_behavior_filetest.gno +++ /dev/null @@ -1,105 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - receiver := string(testutils.TestAddress("zs89-receiver")) - // Regression slot for the current behavior: flat batches have no length cap. - bases := []string{"zs89-a", "zs89-b", "zs89-c", "zs89-d", "zs89-e", "zs89-f", "zs89-g", "zs89-h"} - quoteTokens := make([]string, len(bases)) - instructions := make([]z.Instruction, len(bases)) - for i := 0; i < len(instructions); i++ { - metaBytes := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: bases[i], Symbol: "ZS89", Decimals: 6}) - quoteTokens[i] = z.PredictWrappedTokenV2(u256.Zero(), uint32(pair.Destination), []byte(bases[i]), z.MetadataImage(mustDecodeZS89TokenMetadata(metaBytes))) - instructions[i] = e2e.MustTokenOrderInstruction(cross(cur), z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte(bases[i]), - BaseAmount: u256.NewUint(1), - QuoteToken: []byte(quoteTokens[i]), - QuoteAmount: u256.NewUint(1), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: metaBytes, - }) - } - largeBatch := z.Batch{Instructions: instructions} - largePacket := core.NewPacket(pair.Source, pair.Destination, - e2e.MustPacketData(cross(cur), e2e.MustBatchInstruction(cross(cur), largeBatch)), types.Timestamp(1<<62)) - - println("[SCENARIO] flat allowlisted batch") - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{largePacket}, [][]byte{nil}, nil, 1)) - println("large_batch_receipt", core.HasPacketReceipt(cross(cur), largePacket)) - println("large_batch_success_ack", core.AcknowledgementHash(cross(cur), largePacket).String() == zs89BatchSuccessAckHash(cross(cur), len(instructions))) - println("large_batch_minted_children", zs89MintedChildren(quoteTokens, address(receiver))) - - println("") - println("[SCENARIO] nested batch child rejected by allowlist") - nestedBatch := z.Batch{Instructions: []z.Instruction{ - e2e.MustBatchInstruction(cross(cur), z.Batch{}), - }} - nestedPacket := core.NewPacket(pair.Source, pair.Destination, - e2e.MustPacketData(cross(cur), e2e.MustBatchInstruction(cross(cur), nestedBatch)), types.Timestamp(1<<62)) - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{nestedPacket}, [][]byte{nil}, nil, 1)) - println("nested_batch_receipt", core.HasPacketReceipt(cross(cur), nestedPacket)) - println("nested_batch_failure_ack", core.AcknowledgementHash(cross(cur), nestedPacket).String() == zs89FailureAckHash()) - println("minted_children_after_nested_batch", zs89MintedChildren(quoteTokens, address(receiver))) -} - -func zs89MintedChildren(quoteTokens []string, receiver address) int { - n := 0 - for _, quoteToken := range quoteTokens { - if impl.VoucherBalanceOf(quoteToken, receiver) == 1 { - n++ - } - } - return n -} - -func mustDecodeZS89TokenMetadata(bz []byte) z.TokenMetadata { - meta, err := z.DecodeTokenMetadata(bz) - if err != nil { - panic(err) - } - return meta -} - -func zs89BatchSuccessAckHash(cur realm, count int) string { - childAcks := make([][]byte, count) - for i := 0; i < count; i++ { - childAcks[i] = e2e.MustSuccessAck(cross(cur), e2e.MustProtocolTokenOrderAck(cross(cur))) - } - return types.CommitAcks([][]byte{e2e.MustBatchAck(cross(cur), childAcks)}).String() -} - -func zs89FailureAckHash() string { - ack, err := z.EncodeAck(z.Ack{Tag: u256.NewUint(0), InnerAck: []byte("UNIVERSAL_ERROR")}) - if err != nil { - panic(err) - } - return types.CommitAcks([][]byte{ack}).String() -} - -// Output: -// [SCENARIO] flat allowlisted batch -// large_batch_receipt true -// large_batch_success_ack true -// large_batch_minted_children 8 -// -// [SCENARIO] nested batch child rejected by allowlist -// nested_batch_receipt true -// nested_batch_failure_ack true -// minted_children_after_nested_batch 8 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_denyimpl/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_denyimpl/gnomod.toml deleted file mode 100644 index d2fb25dd..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_denyimpl/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_denyimpl" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_denyimpl/z26_forward_allowedimpls_negative_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_denyimpl/z26_forward_allowedimpls_negative_filetest.gno deleted file mode 100644 index 66c19cc2..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_denyimpl/z26_forward_allowedimpls_negative_filetest.gno +++ /dev/null @@ -1,43 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_denyimpl -package scenarios_denyimpl - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), impl.New(cross(cur)), []string{ - "gno.land/r/onbloc/ibc/union/core", - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm", - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e", - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls", - })) - zkgm.RegisterCoreApp(cross(cur)) - - e2e.RegisterMockLightClient(cross(cur)) - parentChannel := e2e.OpenE2EChannel(cross(cur), types.ChannelId(101)) - childSource := e2e.OpenE2EChannel(cross(cur), types.ChannelId(102)) - - forward := z.Forward{ - Path: e2e.ForwardPath(cross(cur), uint32(parentChannel), uint32(childSource)), - TimeoutTimestamp: 999, - Instruction: e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock"), - ContractCalldata: []byte("forward-core-frame"), - }), - } - packet := core.NewPacket(types.ChannelId(1), parentChannel, - e2e.MustPacketData(cross(cur), e2e.MustForwardInstruction(cross(cur), forward)), types.Timestamp(0)) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) -} - -// Error: -// zkgm: caller is not an authorized impl for set in-flight packet: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/doc.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/doc.gno deleted file mode 100644 index 4d5bbec4..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/doc.gno +++ /dev/null @@ -1 +0,0 @@ -package scenarios_direct diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/gnomod.toml deleted file mode 100644 index 429374b4..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/z1_inflight_events_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/z1_inflight_events_filetest.gno deleted file mode 100644 index 04a13279..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/z1_inflight_events_filetest.gno +++ /dev/null @@ -1,153 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - "chain" - - types "gno.land/p/onbloc/ibc/union/types" - - stdtesting "testing" - - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -type eventReceiver struct{} - -func (r *eventReceiver) OnZkgm(cur realm, env z.CallEnv) error { - return nil -} - -func (r *eventReceiver) OnIntentZkgm(cur realm, env z.IntentCallEnv) error { - return nil -} - -func main(cur realm) { - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), impl.New(cross(cur)), []string{ - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct", - })) - - zkgm.RegisterReceiver(cross(cur), &eventReceiver{}) - stdtesting.IssueCoins(zkgm.ProxyAddress(), chain.NewCoins(chain.NewCoin("ureleaseevent", 9))) - zkgm.ReleaseNative(cross(cur), "ureleaseevent", address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), 9) - - parent := core.NewPacket(types.ChannelId(1), types.ChannelId(2), []byte("parent"), types.Timestamp(10)) - child := core.NewPacket(types.ChannelId(3), types.ChannelId(4), []byte("child"), types.Timestamp(20)) - key := zkgm.NewInFlightKey(cross(cur), types.MustCommit(types.CommitPacket(child))) - value := zkgm.NewInFlightValue(cross(cur), parent) - - zkgm.SetInFlightPacket(cross(cur), key, value) - _, found := zkgm.PopInFlightPacket(cross(cur), key) - _, foundAgain := zkgm.PopInFlightPacket(cross(cur), key) - - println("first_pop", found) - println("second_pop", foundAgain) - println("inflight_events", "ok") -} - -// Output: -// first_pop true -// second_pop false -// inflight_events ok - -// Events: -// [ -// { -// "type": "ZkgmImplUpdated", -// "attrs": [ -// { -// "key": "caller_pkg_path", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct" -// }, -// { -// "key": "old_impl_path", -// "value": "" -// }, -// { -// "key": "new_impl_path", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct" -// }, -// { -// "key": "allowed_impls", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" -// }, -// { -// "type": "ZkgmReceiverRegistered", -// "attrs": [ -// { -// "key": "receiver_pkg_path", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" -// }, -// { -// "type": "ZkgmNativeReleased", -// "attrs": [ -// { -// "key": "caller_pkg_path", -// "value": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct" -// }, -// { -// "key": "denom", -// "value": "ureleaseevent" -// }, -// { -// "key": "recipient", -// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" -// }, -// { -// "key": "amount", -// "value": "9" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" -// }, -// { -// "type": "ZkgmForwardInFlightSet", -// "attrs": [ -// { -// "key": "packet_hash", -// "value": "0x2439f86abd6d0bc03451980414231d33137e303f4d896df3e3f69345257d26fa" -// }, -// { -// "key": "parent_packet_hash", -// "value": "0x400840bbb1b30e67f48a6d65ede08523f569da22608f0836efd16bffce384bb8" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" -// }, -// { -// "type": "ZkgmForwardInFlightPopped", -// "attrs": [ -// { -// "key": "packet_hash", -// "value": "0x2439f86abd6d0bc03451980414231d33137e303f4d896df3e3f69345257d26fa" -// }, -// { -// "key": "found", -// "value": "true" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" -// }, -// { -// "type": "ZkgmForwardInFlightPopped", -// "attrs": [ -// { -// "key": "packet_hash", -// "value": "0x2439f86abd6d0bc03451980414231d33137e303f4d896df3e3f69345257d26fa" -// }, -// { -// "key": "found", -// "value": "false" -// } -// ], -// "pkg_path": "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" -// } -// ] diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs21_lock_mint_unescrow_unlock_conservation_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs21_lock_mint_unescrow_unlock_conservation_filetest.gno deleted file mode 100644 index c2ef56ad..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs21_lock_mint_unescrow_unlock_conservation_filetest.gno +++ /dev/null @@ -1,104 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - "chain" - "chain/banker" - - types "gno.land/p/onbloc/ibc/union/types" - - stdtesting "testing" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - sourceChannel := types.ChannelId(10) - destChannel := types.ChannelId(11) - sender := "g17xpfvakm2amg962yls6f84z3kell8c5lserqta" - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - relayer := testutils.TestAddress("zs21-relayer") - meta := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Roundtrip GNOT", Symbol: "RGNOT", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(destChannel), []byte("ugnot"), z.MetadataImage(sh.DecodeTokenMetadata(meta))) - - println("[SCENARIO] lock native on source") - lockOrder := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(40), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(40), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: meta, - } - lockInstr := e2e.MustTokenOrderInstruction(cross(cur), lockOrder) - lockData, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), sourceChannel, types.Timestamp(100), [32]byte{}, lockInstr, sender, "40ugnot")) - if err != nil { - panic(err) - } - println("source_channel_balance_after_lock", sh.ChannelBalanceStr(sourceChannel, u256.Zero(), lockOrder.BaseToken, lockOrder.QuoteToken)) - - println("") - println("[SCENARIO] mint voucher on destination") - lockPacket := core.NewPacket(sourceChannel, destChannel, lockData, types.Timestamp(100)) - recvRes := inst.Recv(cross(cur), lockPacket, relayer, nil) - println("recv_status", int(recvRes.Status)) - println("receiver_voucher_after_mint", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] burn voucher for unescrow send") - unescrowOrder := z.TokenOrderV2{ - Sender: []byte(receiver), - Receiver: []byte(sender), - BaseToken: []byte(quoteToken), - BaseAmount: u256.NewUint(40), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(40), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - unescrowInstr := e2e.MustTokenOrderInstruction(cross(cur), unescrowOrder) - unescrowData, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), destChannel, types.Timestamp(101), [32]byte{}, unescrowInstr, receiver, "")) - if err != nil { - panic(err) - } - println("receiver_voucher_after_unescrow_send", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] unlock native on source") - // inst.Send consumes sentCoinBudget bookkeeping only; this simulates the - // banker escrow deposit that a real user tx would have locked in the proxy. - stdtesting.IssueCoins(zkgm.ProxyAddress(), chain.NewCoins(chain.NewCoin("ugnot", 40))) - unescrowPacket := core.NewPacket(destChannel, sourceChannel, unescrowData, types.Timestamp(101)) - unescrowRes := inst.Recv(cross(cur), unescrowPacket, relayer, nil) - bk := banker.NewReadonlyBanker() - println("unescrow_recv_status", int(unescrowRes.Status)) - println("source_channel_balance_after_unlock", sh.ChannelBalanceStr(sourceChannel, u256.Zero(), lockOrder.BaseToken, lockOrder.QuoteToken)) - println("sender_native_after_unlock", bk.GetCoins(address(sender)).AmountOf("ugnot")) - println("receiver_voucher_final", impl.VoucherBalanceOf(quoteToken, address(receiver))) -} - -// Output: -// [SCENARIO] lock native on source -// source_channel_balance_after_lock 40 -// -// [SCENARIO] mint voucher on destination -// recv_status 1 -// receiver_voucher_after_mint 40 -// -// [SCENARIO] burn voucher for unescrow send -// receiver_voucher_after_unescrow_send 0 -// -// [SCENARIO] unlock native on source -// unescrow_recv_status 1 -// source_channel_balance_after_unlock 0 -// sender_native_after_unlock 40 -// receiver_voucher_final 0 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs22_fee_distribution_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs22_fee_distribution_filetest.gno deleted file mode 100644 index 70ba080a..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs22_fee_distribution_filetest.gno +++ /dev/null @@ -1,91 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - "chain" - "chain/banker" - - types "gno.land/p/onbloc/ibc/union/types" - - stdtesting "testing" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - relayer := testutils.TestAddress("zs22-relayer") - receiver := string(testutils.TestAddress("zs22-receiver")) - escrowChannel := types.ChannelId(21) - unescrowChannel := types.ChannelId(22) - meta := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Fee Token", Symbol: "FEE", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(escrowChannel), []byte("ufee"), z.MetadataImage(sh.DecodeTokenMetadata(meta))) - - println("[SCENARIO] escrow recv fee mints voucher split") - escrowOrder := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ufee"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(88), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: meta, - } - escrowPacket := core.NewPacket(types.ChannelId(20), escrowChannel, sh.TokenOrderPacketData(cross(cur), escrowOrder), types.Timestamp(100)) - inst.Recv(cross(cur), escrowPacket, relayer, nil) - println("receiver_voucher", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("relayer_voucher_fee", impl.VoucherBalanceOf(quoteToken, relayer)) - - println("") - println("[SCENARIO] unescrow recv fee releases native split") - nativeLock := z.TokenOrderV2{ - Sender: []byte(testutils.TestAddress("zs22-native-sender").String()), - Receiver: []byte(testutils.TestAddress("zs22-counterparty").String()), - BaseToken: []byte("ufee"), - BaseAmount: u256.NewUint(55), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(55), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - lockData, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), unescrowChannel, types.Timestamp(101), [32]byte{}, e2e.MustTokenOrderInstruction(cross(cur), nativeLock), string(nativeLock.Sender), "55ufee")) - if err != nil { - panic(err) - } - _ = lockData - nativeOrder := z.TokenOrderV2{ - Sender: []byte(testutils.TestAddress("zs22-counterparty").String()), - Receiver: []byte(receiver), - BaseToken: []byte(quoteToken), - BaseAmount: u256.NewUint(55), - QuoteToken: []byte("ufee"), - QuoteAmount: u256.NewUint(50), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - // inst.Send consumes sentCoinBudget bookkeeping only; this simulates the - // banker escrow deposit that a real user tx would have locked in the proxy. - stdtesting.IssueCoins(zkgm.ProxyAddress(), chain.NewCoins(chain.NewCoin("ufee", 55))) - unescrowPacket := core.NewPacket(types.ChannelId(23), unescrowChannel, sh.TokenOrderPacketData(cross(cur), nativeOrder), types.Timestamp(102)) - inst.Recv(cross(cur), unescrowPacket, relayer, nil) - bk := banker.NewReadonlyBanker() - println("receiver_native", bk.GetCoins(address(receiver)).AmountOf("ufee")) - println("relayer_native_fee", bk.GetCoins(relayer).AmountOf("ufee")) - println("unescrow_channel_balance", sh.ChannelBalanceStr(unescrowChannel, u256.Zero(), nativeOrder.QuoteToken, nativeOrder.BaseToken)) -} - -// Output: -// [SCENARIO] escrow recv fee mints voucher split -// receiver_voucher 88 -// relayer_voucher_fee 12 -// -// [SCENARIO] unescrow recv fee releases native split -// receiver_native 50 -// relayer_native_fee 5 -// unescrow_channel_balance 0 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs23_ack_failure_refund_success_settlement_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs23_ack_failure_refund_success_settlement_filetest.gno deleted file mode 100644 index b70b9bce..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs23_ack_failure_refund_success_settlement_filetest.gno +++ /dev/null @@ -1,89 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - senderRefund := string(testutils.TestAddress("zs23-refund-sender")) - senderSuccess := string(testutils.TestAddress("zs23-success-sender")) - refundBaseToken := sh.MintVoucher(cross(cur), inst, types.ChannelId(30), "base/zs23-refund", senderRefund, 100, "ZS23") - successBaseToken := sh.MintVoucher(cross(cur), inst, types.ChannelId(31), "base/zs23-success", senderSuccess, 100, "ZS23") - refundChannel := types.ChannelId(32) - successChannel := types.ChannelId(33) - - println("[SCENARIO] send-side escrow for both branches") - refundOrder := zs23Order(senderRefund, refundBaseToken) - successOrder := zs23Order(senderSuccess, successBaseToken) - refundPacket := zs23Send(cross(cur), inst, refundChannel, senderRefund, refundOrder) - successPacket := zs23Send(cross(cur), inst, successChannel, senderSuccess, successOrder) - println("refund_sender_after_send", impl.VoucherBalanceOf(refundBaseToken, address(senderRefund))) - println("success_sender_after_send", impl.VoucherBalanceOf(successBaseToken, address(senderSuccess))) - println("refund_channel_after_send", sh.ChannelBalanceStr(refundChannel, u256.Zero(), refundOrder.BaseToken, refundOrder.QuoteToken)) - println("success_channel_after_send", sh.ChannelBalanceStr(successChannel, u256.Zero(), successOrder.BaseToken, successOrder.QuoteToken)) - - println("") - println("[SCENARIO] failure ack refunds sender") - inst.Ack(cross(cur), refundPacket, zs23FailureAckBytes(), testutils.TestAddress("zs23-relayer")) - println("refund_sender_after_failure_ack", impl.VoucherBalanceOf(refundBaseToken, address(senderRefund))) - println("refund_channel_after_failure_ack", sh.ChannelBalanceStr(refundChannel, u256.Zero(), refundOrder.BaseToken, refundOrder.QuoteToken)) - - println("") - println("[SCENARIO] success protocol ack leaves escrow settled") - inst.Ack(cross(cur), successPacket, e2e.MustSuccessAck(cross(cur), e2e.MustProtocolTokenOrderAck(cross(cur))), testutils.TestAddress("zs23-relayer")) - println("success_sender_after_success_ack", impl.VoucherBalanceOf(successBaseToken, address(senderSuccess))) - println("success_channel_after_success_ack", sh.ChannelBalanceStr(successChannel, u256.Zero(), successOrder.BaseToken, successOrder.QuoteToken)) -} - -func zs23Order(sender string, baseToken string) z.TokenOrderV2 { - return z.TokenOrderV2{ - Sender: []byte(sender), - BaseToken: []byte(baseToken), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte("quote/zs23"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } -} - -func zs23Send(cur realm, inst zkgm.ZkgmImpl, channelId types.ChannelId, sender string, order z.TokenOrderV2) types.Packet { - data, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), channelId, types.Timestamp(120), [32]byte{}, e2e.MustTokenOrderInstruction(cross(cur), order), sender, "")) - if err != nil { - panic(err) - } - return core.NewPacket(channelId, types.ChannelId(99), data, types.Timestamp(120)) -} - -func zs23FailureAckBytes() []byte { - ack, err := z.EncodeAck(z.Ack{Tag: new(u256.Uint).SetBytes(z.TAG_ACK_FAILURE[:])}) - if err != nil { - panic(err) - } - return ack -} - -// Output: -// [SCENARIO] send-side escrow for both branches -// refund_sender_after_send 79 -// success_sender_after_send 79 -// refund_channel_after_send 21 -// success_channel_after_send 21 -// -// [SCENARIO] failure ack refunds sender -// refund_sender_after_failure_ack 100 -// refund_channel_after_failure_ack 0 -// -// [SCENARIO] success protocol ack leaves escrow settled -// success_sender_after_success_ack 79 -// success_channel_after_success_ack 21 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs24_market_maker_fill_settlement_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs24_market_maker_fill_settlement_filetest.gno deleted file mode 100644 index fd6b4908..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs24_market_maker_fill_settlement_filetest.gno +++ /dev/null @@ -1,80 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - sender := string(testutils.TestAddress("zs24-sender")) - receiver := string(testutils.TestAddress("zs24-receiver")) - marketMaker := testutils.TestAddress("zs24-market-maker") - baseToken := sh.MintVoucher(cross(cur), inst, types.ChannelId(40), "base/zs24", sender, 30, "ZS24") - quoteToken := sh.MintVoucher(cross(cur), inst, types.ChannelId(41), "quote/zs24", marketMaker.String(), 12, "ZS24") - channelId := types.ChannelId(42) - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte(receiver), - BaseToken: []byte(baseToken), - BaseAmount: u256.NewUint(30), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(12), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - - println("[SCENARIO] market maker fills quote side") - intentPacket := core.NewPacket(types.ChannelId(99), types.ChannelId(98), e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(100)) - intentRes := inst.IntentRecv(cross(cur), intentPacket, marketMaker, nil) - println("intent_status", int(intentRes.Status)) - println("market_maker_quote_after_fill", impl.VoucherBalanceOf(quoteToken, marketMaker)) - println("receiver_quote_after_fill", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] proven ack settles recorded maker") - sendData, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), channelId, types.Timestamp(101), [32]byte{}, e2e.MustTokenOrderInstruction(cross(cur), order), sender, "")) - if err != nil { - panic(err) - } - sourcePacket := core.NewPacket(channelId, types.ChannelId(100), sendData, types.Timestamp(101)) - println("sender_base_after_send", impl.VoucherBalanceOf(baseToken, address(sender))) - println("channel_after_send", sh.ChannelBalanceStr(channelId, u256.Zero(), order.BaseToken, order.QuoteToken)) - inst.Ack(cross(cur), sourcePacket, intentRes.Acknowledgement, testutils.TestAddress("zs24-relayer")) - println("ack_market_maker_recorded", zs24AckMarketMaker(intentRes.Acknowledgement) == marketMaker.String()) - println("market_maker_base_after_ack", impl.VoucherBalanceOf(baseToken, marketMaker)) - println("channel_after_ack", sh.ChannelBalanceStr(channelId, u256.Zero(), order.BaseToken, order.QuoteToken)) -} - -func zs24AckMarketMaker(ackBytes []byte) string { - ack, err := z.DecodeAck(ackBytes) - if err != nil { - panic(err) - } - orderAck, err := z.DecodeTokenOrderAck(ack.InnerAck) - if err != nil { - panic(err) - } - return string(orderAck.MarketMaker) -} - -// Output: -// [SCENARIO] market maker fills quote side -// intent_status 1 -// market_maker_quote_after_fill 0 -// receiver_quote_after_fill 12 -// -// [SCENARIO] proven ack settles recorded maker -// sender_base_after_send 0 -// channel_after_send 30 -// ack_market_maker_recorded true -// market_maker_base_after_ack 30 -// channel_after_ack 0 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs25_18dec_no_scaling_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs25_18dec_no_scaling_filetest.gno deleted file mode 100644 index 21bcb89c..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs25_18dec_no_scaling_filetest.gno +++ /dev/null @@ -1,64 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - const amount = uint64(1000000000000000000) - inst := sh.InstallV1Harness(cross(cur)) - destChannel := types.ChannelId(51) - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - meta := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Ether Token", Symbol: "ETH", Decimals: 18}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(destChannel), []byte("wei"), z.MetadataImage(sh.DecodeTokenMetadata(meta))) - - println("[SCENARIO] recv 18-dec initialize without amount scaling") - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("wei"), - BaseAmount: u256.NewUint(amount), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(amount), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: meta, - } - packet := core.NewPacket(types.ChannelId(50), destChannel, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(100)) - inst.Recv(cross(cur), packet, testutils.TestAddress("zs25-relayer"), nil) - println("voucher_decimals", impl.VoucherDecimalsOf(quoteToken)) - println("receiver_balance", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] unescrow send burns the same 18-dec amount") - unescrowOrder := z.TokenOrderV2{ - Sender: []byte(receiver), - Receiver: []byte("sender"), - BaseToken: []byte(quoteToken), - BaseAmount: u256.NewUint(amount), - QuoteToken: []byte("wei"), - QuoteAmount: u256.NewUint(amount), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - if _, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), destChannel, types.Timestamp(101), [32]byte{}, e2e.MustTokenOrderInstruction(cross(cur), unescrowOrder), receiver, "")); err != nil { - panic(err) - } - println("receiver_balance_after_burn", impl.VoucherBalanceOf(quoteToken, address(receiver))) -} - -// Output: -// [SCENARIO] recv 18-dec initialize without amount scaling -// voucher_decimals 18 -// receiver_balance 1000000000000000000 -// -// [SCENARIO] unescrow send burns the same 18-dec amount -// receiver_balance_after_burn 0 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs26_6dec_native_out_no_scaling_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs26_6dec_native_out_no_scaling_filetest.gno deleted file mode 100644 index e9c6f635..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs26_6dec_native_out_no_scaling_filetest.gno +++ /dev/null @@ -1,38 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" -) - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - channelId := types.ChannelId(61) - amount := u256.NewUint(1234567) - order := z.TokenOrderV2{ - Sender: []byte("g16decsender"), - BaseToken: []byte("ugnot"), - BaseAmount: amount, - QuoteToken: []byte("quote/zs26"), - QuoteAmount: amount, - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - - println("[SCENARIO] native 6-dec send preserves base amount") - if _, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), channelId, types.Timestamp(100), [32]byte{}, e2e.MustTokenOrderInstruction(cross(cur), order), string(order.Sender), "1234567ugnot")); err != nil { - panic(err) - } - println("base_amount", order.BaseAmount.ToString()) - println("channel_balance", sh.ChannelBalanceStr(channelId, u256.Zero(), order.BaseToken, order.QuoteToken)) -} - -// Output: -// [SCENARIO] native 6-dec send preserves base amount -// base_amount 1234567 -// channel_balance 1234567 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs33_v1_registration_config_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs33_v1_registration_config_filetest.gno deleted file mode 100644 index 48cf41aa..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs33_v1_registration_config_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" -) - -func main(cur realm) { - impl.Register(cross(cur)) - - println("[SCENARIO] 1. v1 registers proxy") - println("[EXPECTED] bootstrapped", zkgm.Bootstrapped()) - println("[EXPECTED] impl_path", zkgm.ImplPath()) - println("[EXPECTED] allowed_count", len(zkgm.AllowedImpls())) - println("[EXPECTED] loader_allowed", zkgm.InAllowedImpls("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/loader")) -} - -// Output: -// [SCENARIO] 1. v1 registers proxy -// [EXPECTED] bootstrapped true -// [EXPECTED] impl_path gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1 -// [EXPECTED] allowed_count 0 -// [EXPECTED] loader_allowed false diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs64_voucher_asymmetry_origin_halt_no_recovery_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs64_voucher_asymmetry_origin_halt_no_recovery_filetest.gno deleted file mode 100644 index e41f9459..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs64_voucher_asymmetry_origin_halt_no_recovery_filetest.gno +++ /dev/null @@ -1,117 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - "chain" - "chain/banker" - - types "gno.land/p/onbloc/ibc/union/types" - - stdtesting "testing" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - "gno.land/p/nt/uassert/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/nonimpl" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - sourceChannel := types.ChannelId(10) - destChannel := types.ChannelId(11) - sender := "g17xpfvakm2amg962yls6f84z3kell8c5lserqta" - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - relayer := testutils.TestAddress("zs64-relayer") - meta := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Halted Origin GNOT", Symbol: "HOGNOT", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(destChannel), []byte("ugnot"), z.MetadataImage(sh.DecodeTokenMetadata(meta))) - - println("[SCENARIO] lock native on source") - lockOrder := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(40), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(40), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: meta, - } - lockInstr := e2e.MustTokenOrderInstruction(cross(cur), lockOrder) - lockData, err := inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), sourceChannel, types.Timestamp(100), [32]byte{}, lockInstr, sender, "40ugnot")) - if err != nil { - panic(err) - } - // inst.Send consumes sentCoinBudget bookkeeping only; this mirrors the - // banker escrow deposit that a real user tx would have locked in the proxy. - stdtesting.IssueCoins(zkgm.ProxyAddress(), chain.NewCoins(chain.NewCoin("ugnot", 40))) - println("source_channel_balance_after_lock", sh.ChannelBalanceStr(sourceChannel, u256.Zero(), lockOrder.BaseToken, lockOrder.QuoteToken)) - println("proxy_native_after_lock", banker.NewReadonlyBanker().GetCoins(zkgm.ProxyAddress()).AmountOf("ugnot")) - - println("") - println("[SCENARIO] mint voucher on destination") - lockPacket := core.NewPacket(sourceChannel, destChannel, lockData, types.Timestamp(100)) - recvRes := inst.Recv(cross(cur), lockPacket, relayer, nil) - println("recv_status", int(recvRes.Status)) - println("receiver_voucher_after_mint", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] burn voucher for unescrow send") - unescrowOrder := z.TokenOrderV2{ - Sender: []byte(receiver), - Receiver: []byte(sender), - BaseToken: []byte(quoteToken), - BaseAmount: u256.NewUint(40), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(40), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - unescrowInstr := e2e.MustTokenOrderInstruction(cross(cur), unescrowOrder) - _, err = inst.Send(cross(cur), zkgm.NewSendRequest(cross(cur), destChannel, types.Timestamp(101), [32]byte{}, unescrowInstr, receiver, "")) - if err != nil { - panic(err) - } - println("receiver_voucher_after_unescrow_send", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] origin halted: unescrow recv never delivered") - // A halted origin cannot process the unescrow packet, and timeout refund - // also requires a fresh non-membership proof from that halted origin. - bk := banker.NewReadonlyBanker() - println("source_channel_balance_after_halt", sh.ChannelBalanceStr(sourceChannel, u256.Zero(), lockOrder.BaseToken, lockOrder.QuoteToken)) - println("proxy_native_after_halt", bk.GetCoins(zkgm.ProxyAddress()).AmountOf("ugnot")) - println("sender_native_after_halt", bk.GetCoins(address(sender)).AmountOf("ugnot")) - println("receiver_voucher_final", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("release_native_unauthorized_caller_rejected", releaseNativeUnauthorizedCallerRejected(cur)) -} - -func releaseNativeUnauthorizedCallerRejected(cur realm) bool { - var tt *stdtesting.T - return uassert.AbortsContains(tt, cur, "not an authorized impl", func(cur realm) { - nonimpl.ReleaseNativeDirect(cross(cur)) - }) -} - -// Output: -// [SCENARIO] lock native on source -// source_channel_balance_after_lock 40 -// proxy_native_after_lock 40 -// -// [SCENARIO] mint voucher on destination -// recv_status 1 -// receiver_voucher_after_mint 40 -// -// [SCENARIO] burn voucher for unescrow send -// receiver_voucher_after_unescrow_send 0 -// -// [SCENARIO] origin halted: unescrow recv never delivered -// source_channel_balance_after_halt 40 -// proxy_native_after_halt 40 -// sender_native_after_halt 0 -// receiver_voucher_final 0 -// release_native_unauthorized_caller_rejected true diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs86_intent_frontrun_and_call_failclosed_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs86_intent_frontrun_and_call_failclosed_filetest.gno deleted file mode 100644 index b6077b17..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs86_intent_frontrun_and_call_failclosed_filetest.gno +++ /dev/null @@ -1,80 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const zs86MockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - e2e.RegisterMockLightClient(cross(cur)) - pair := e2e.OpenE2EChannelPair(cross(cur)) - - marketMaker := cur.Address() - receiver := string(testutils.TestAddress("zs86-receiver")) - quoteToken := sh.MintVoucher(cross(cur), inst, pair.Destination, "zs86-base", marketMaker.String(), 12, "ZS86") - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("remote-base"), - BaseAmount: u256.NewUint(12), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(12), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - intentPacket := core.NewPacket(pair.Source, pair.Destination, - e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(1<<62)) - - println("[SCENARIO] fillable token order intent preempts proven recv") - core.IntentPacketRecv(cross(cur), types.NewMsgIntentPacketRecv([]types.Packet{intentPacket}, [][]byte{nil})) - println("maker_quote_after_intent", impl.VoucherBalanceOf(quoteToken, marketMaker)) - println("receiver_quote_after_intent", impl.VoucherBalanceOf(quoteToken, address(receiver))) - println("intent_receipt", core.HasPacketReceipt(cross(cur), intentPacket)) - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{intentPacket}, [][]byte{nil}, nil, 1)) - println("receiver_quote_after_proven_recv", impl.VoucherBalanceOf(quoteToken, address(receiver))) - - println("") - println("[SCENARIO] op call intent fails closed before receiver") - mock.Reset(cross(cur)) - callPacket := core.NewPacket(pair.Source, pair.Destination, - e2e.MustPacketData(cross(cur), e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(zs86MockReceiverPath), - ContractCalldata: []byte("intent-call"), - })), types.Timestamp(1<<62)) - println("call_intent_reverted", zs86IntentRecvReverted(cur, callPacket)) - println("call_mock_calls", mock.Calls(cross(cur))) - // revive catches the panic inside this filetest transaction, so the receipt - // write is observable here. A top-level failed tx would roll this state back. - println("call_receipt_in_recovered_harness", core.HasPacketReceipt(cross(cur), callPacket)) -} - -func zs86IntentRecvReverted(cur realm, packet types.Packet) (reverted bool) { - p := revive(func() { - core.IntentPacketRecv(cross(cur), types.NewMsgIntentPacketRecv([]types.Packet{packet}, [][]byte{nil})) - }) - return p != nil -} - -// Output: -// [SCENARIO] fillable token order intent preempts proven recv -// maker_quote_after_intent 0 -// receiver_quote_after_intent 12 -// intent_receipt true -// receiver_quote_after_proven_recv 12 -// -// [SCENARIO] op call intent fails closed before receiver -// call_intent_reverted true -// call_mock_calls 0 -// call_receipt_in_recovered_harness true diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs88_recv_path_ignores_send_rate_limit_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs88_recv_path_ignores_send_rate_limit_filetest.gno deleted file mode 100644 index 2ca3b84d..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/e2e/scenarios_direct/zs88_recv_path_ignores_send_rate_limit_filetest.gno +++ /dev/null @@ -1,57 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct -package scenarios_direct - -import ( - stdtesting "testing" - - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - tb "gno.land/p/onbloc/ibc/union/zkgm/tokenbucket" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - sh "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - inst := sh.InstallV1Harness(cross(cur)) - receiver := string(testutils.TestAddress("zs88-receiver")) - baseToken := "rate-limited-base" - channelId := types.ChannelId(88) - - bucket, err := tb.New(u256.NewUint(1), u256.NewUint(1), u256.NewUint(1)) - if err != nil { - panic(err) - } - stdtesting.SetRealm(stdtesting.NewCodeRealm(zkgm.ProductionImplPath())) - zkgm.SetTokenBucket(cross(cur), baseToken, bucket) - stdtesting.SetRealm(stdtesting.NewCodeRealm("gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e/scenarios_direct")) - - metaBytes := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: "Rate Limited", Symbol: "RL", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte(baseToken), z.MetadataImage(sh.DecodeTokenMetadata(metaBytes))) - order := z.TokenOrderV2{ - Sender: []byte("remote"), - Receiver: []byte(receiver), - BaseToken: []byte(baseToken), - BaseAmount: u256.NewUint(25), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(25), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: metaBytes, - } - packet := core.NewPacket(types.ChannelId(1), channelId, sh.TokenOrderPacketData(cross(cur), order), types.Timestamp(100)) - - println("[SCENARIO] recv mint is not charged against send-side bucket") - res := inst.Recv(cross(cur), packet, testutils.TestAddress("zs88-relayer"), nil) - println("recv_status", int(res.Status)) - println("receiver_balance", impl.VoucherBalanceOf(quoteToken, address(receiver))) -} - -// Output: -// [SCENARIO] recv mint is not charged against send-side bucket -// recv_status 1 -// receiver_balance 25 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/gnomod.toml deleted file mode 100644 index 54b08fde..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/impl_isolation" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/z50_impl_direct_construct_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/z50_impl_direct_construct_filetest.gno deleted file mode 100644 index 750a48d5..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/z50_impl_direct_construct_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/impl_isolation -package impl_isolation - -import ( - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" -) - -// A foreign realm cannot bypass core by constructing impl.ZkgmV1 directly and -// calling its crossing state-change methods: -// -// (&impl.ZkgmV1{}).Recv(cross(cur), craftedUnescrowPacket, caller, nil) -// -// Gno Phase 3 makes that structurally impossible: a realm cannot allocate a -// struct type owned by another realm. Allocation aborts before any -// Recv/IntentRecv/Ack/Timeout/Send method can run. -func main(cur realm) { - _ = &impl.ZkgmV1{} -} - -// Error: -// cannot allocate gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1.ZkgmV1 in realm gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/impl_isolation diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/z51_impl_new_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/z51_impl_new_filetest.gno deleted file mode 100644 index 06a42968..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/impl_isolation/z51_impl_new_filetest.gno +++ /dev/null @@ -1,18 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/impl_isolation -package impl_isolation - -import ( - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" -) - -// New is the other path to a callable *ZkgmV1. Register installs the impl and -// sets zkgm.ImplPath() to the production impl realm. After that, New only -// serves that realm. A foreign caller is rejected before it can obtain an impl -// object needed to call Recv/IntentRecv/Ack/Timeout/Send. -func main(cur realm) { - impl.Register(cross(cur)) - _ = impl.New(cross(cur)) -} - -// Error: -// not allowed diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/mock/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/mock/gnomod.toml deleted file mode 100644 index 3a8235a4..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/mock/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/nonimpl/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/nonimpl/gnomod.toml deleted file mode 100644 index d763b895..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/nonimpl/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/nonimpl" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/nonimpl/nonimpl.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/nonimpl/nonimpl.gno deleted file mode 100644 index b9f08466..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/nonimpl/nonimpl.gno +++ /dev/null @@ -1,10 +0,0 @@ -package nonimpl - -import ( - "gno.land/p/nt/testutils/v0" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" -) - -func ReleaseNativeDirect(cur realm) { - zkgm.ReleaseNative(cross(cur), "ugnot", testutils.TestAddress("nonimpl-recipient"), 1) -} diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/gnomod.toml deleted file mode 100644 index 515ae38b..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/doc.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/doc.gno deleted file mode 100644 index dbef7c9b..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/doc.gno +++ /dev/null @@ -1 +0,0 @@ -package scenarios diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/gnomod.toml deleted file mode 100644 index b8fe7804..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z31_real_cometbls_create_update_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z31_real_cometbls_create_update_filetest.gno deleted file mode 100644 index 8001ae71..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z31_real_cometbls_create_update_filetest.gno +++ /dev/null @@ -1,28 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - height := realcometbls.UpdateRealCometBLSClient(cross(cur), clientId) - latestHeight := realadapter.NewAdapter(cross(cur)).GetLatestHeight(clientId) - timestamp := realadapter.NewAdapter(cross(cur)).GetTimestamp(clientId, height) - status := realadapter.NewAdapter(cross(cur)).GetStatus(clientId) - - println("client_id", clientId.String()) - println("updated_height", height.String()) - println("latest_height", latestHeight.String()) - println("timestamp", timestamp.String()) - println("status", uint8(status)) -} - -// Output: -// client_id 1 -// updated_height 3405691582 -// latest_height 3405691582 -// timestamp 1732205251998131342 -// status 1 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z32_real_cometbls_rejects_bad_header_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z32_real_cometbls_rejects_bad_header_filetest.gno deleted file mode 100644 index ff047b64..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z32_real_cometbls_rejects_bad_header_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - realcometbls.UpdateRealCometBLSClientWithTamperedHeader(cross(cur), clientId) -} - -// Error: -// cometbls: cometblszk: invalid proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z33_real_cometbls_membership_fixture_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z33_real_cometbls_membership_fixture_filetest.gno deleted file mode 100644 index 0a86e6df..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z33_real_cometbls_membership_fixture_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateSyntheticCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticMembershipProof(cross(cur)), - realcometbls.SyntheticMembershipKey(cross(cur)), - realcometbls.SyntheticMembershipValue(cross(cur)), - ) - - println("membership_fixture", "ok") -} - -// Output: -// membership_fixture ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z34_real_cometbls_non_membership_fixture_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z34_real_cometbls_non_membership_fixture_filetest.gno deleted file mode 100644 index 2a8fd16b..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z34_real_cometbls_non_membership_fixture_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateSyntheticCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyNonMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticNonMembershipProof(cross(cur)), - realcometbls.SyntheticNonMembershipKey(cross(cur)), - ) - - println("non_membership_fixture", "ok") -} - -// Output: -// non_membership_fixture ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z35_open_channel_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z35_open_channel_filetest.gno deleted file mode 100644 index 5a6f3bdb..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z35_open_channel_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - - println("client", pair.ClientId.String()) - println("connection", pair.ConnectionId.String()) - println("source", pair.Source.String()) - println("destination", pair.Destination.String()) -} - -// Output: -// client 1 -// connection 1 -// source 2 -// destination 1 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z35_real_cometbls_recv_token_order_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z35_real_cometbls_recv_token_order_filetest.gno deleted file mode 100644 index 0db95348..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z35_real_cometbls_recv_token_order_filetest.gno +++ /dev/null @@ -1,47 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte("ibc/quote"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(0)) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, realcometbls.Z35PacketCommitmentProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("quote_balance", impl.VoucherBalanceOf("ibc/quote", address(receiver))) - println("ack_hash_matches_failure", core.AcknowledgementHash(cross(cur), packet).String() == expectedFailureAckHash()) -} - -func expectedFailureAckHash() string { - ack, err := z.EncodeAck(z.Ack{Tag: u256.NewUint(0), InnerAck: []byte("UNIVERSAL_ERROR")}) - if err != nil { - panic(err) - } - return types.CommitAcks([][]byte{ack}).String() -} - -// Output: -// quote_balance 0 -// ack_hash_matches_failure true diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z38a_recv_packet_receipt_dup_guard_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z38a_recv_packet_receipt_dup_guard_filetest.gno deleted file mode 100644 index 727fe0c5..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z38a_recv_packet_receipt_dup_guard_filetest.gno +++ /dev/null @@ -1,53 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - order := z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte("ibc/quote"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - } - packet := core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(0)) - msg := types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, realcometbls.Z35PacketCommitmentProof(cross(cur)), uint64(realcometbls.DevnetHeight-1)) - - core.PacketRecv(cross(cur), msg) - println("quote_balance_after_first_recv", impl.VoucherBalanceOf("ibc/quote", address(receiver))) - - core.PacketRecv(cross(cur), msg) - println("quote_balance_after_second_recv", impl.VoucherBalanceOf("ibc/quote", address(receiver))) - println("ack_hash_matches_failure", core.AcknowledgementHash(cross(cur), packet).String() == expectedFailureAckHash()) - println("duplicate_recv_noop", "ok") -} - -func expectedFailureAckHash() string { - ack, err := z.EncodeAck(z.Ack{Tag: u256.NewUint(0), InnerAck: []byte("UNIVERSAL_ERROR")}) - if err != nil { - panic(err) - } - return types.CommitAcks([][]byte{ack}).String() -} - -// Output: -// quote_balance_after_first_recv 0 -// quote_balance_after_second_recv 0 -// ack_hash_matches_failure true -// duplicate_recv_noop ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39_fixture_inputs_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39_fixture_inputs_filetest.gno deleted file mode 100644 index da85a1a2..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39_fixture_inputs_filetest.gno +++ /dev/null @@ -1,52 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - "encoding/hex" - - types "gno.land/p/onbloc/ibc/union/types" - - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - core "gno.land/r/onbloc/ibc/union/core" -) - -const ( - mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - missingReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/missing" -) - -func main(cur realm) { - packet := z39CallPacket(cur, mockReceiverPath) - packetKey := types.MustCommit(types.PacketCommitmentPath(packet)) - packetValue := types.COMMITMENT_MAGIC - missingPacket := z39CallPacket(cur, missingReceiverPath) - missingPacketKey := types.MustCommit(types.PacketCommitmentPath(missingPacket)) - - printKV("call_packet_commitment", packetKey[:], packetValue[:]) - println("packet_data", "0x"+hex.EncodeToString(packet.Data)) - printKV("missing_call_packet_commitment", missingPacketKey[:], packetValue[:]) - println("missing_packet_data", "0x"+hex.EncodeToString(missingPacket.Data)) -} - -func z39CallPacket(cur realm, receiverPath string) types.Packet { - call := z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(receiverPath), - ContractCalldata: []byte("calldata"), - } - return core.NewPacket(types.ChannelId(2), types.ChannelId(1), e2e.MustPacketData(cross(cur), e2e.MustCallInstruction(cross(cur), call)), types.Timestamp(0)) -} - -func printKV(name string, key []byte, value []byte) { - println(name+"_key", "0x"+hex.EncodeToString(key)) - println(name+"_value", "0x"+hex.EncodeToString(value)) -} - -// Output: -// call_packet_commitment_key 0xf9fc75d51d473e980f2141b006da2897766da9ce36737c10b7d6444dc4c94ae6 -// call_packet_commitment_value 0x0100000000000000000000000000000000000000000000000000000000000000 -// packet_data 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000673656e64657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038676e6f2e6c616e642f722f6f6e626c6f632f6962632f756e696f6e2f617070732f75637330335f7a6b676d2f74657374696e672f6d6f636b0000000000000000000000000000000000000000000000000000000000000000000000000000000863616c6c64617461000000000000000000000000000000000000000000000000 -// missing_call_packet_commitment_key 0x370fc261c739d70a11a370a82a6f1ccbb2ddd55ae0f5a9e6abfed94462e9d303 -// missing_call_packet_commitment_value 0x0100000000000000000000000000000000000000000000000000000000000000 -// missing_packet_data 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000673656e6465720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b676e6f2e6c616e642f722f6f6e626c6f632f6962632f756e696f6e2f617070732f75637330335f7a6b676d2f74657374696e672f6d697373696e670000000000000000000000000000000000000000000000000000000000000000000000000863616c6c64617461000000000000000000000000000000000000000000000000 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39a_recv_call_dispatches_via_real_lc_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39a_recv_call_dispatches_via_real_lc_filetest.gno deleted file mode 100644 index eb952703..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39a_recv_call_dispatches_via_real_lc_filetest.gno +++ /dev/null @@ -1,50 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func main(cur realm) { - impl.Register(cross(cur)) - mock.Reset(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - packet := callPacket(cur, pair, mockReceiverPath) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{[]byte("relay-msg")}, realcometbls.Z39CallPacketCommitmentProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("mock_calls", mock.Calls(cross(cur))) - println("last_sender", mock.LastSender(cross(cur))) - println("last_calldata", mock.LastCalldata(cross(cur))) - println("last_relayer_msg", mock.LastRelayerMsg(cross(cur))) - println("receipt_after_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_recv", core.HasAcknowledgement(cross(cur), packet)) - println("recv_call_dispatch_real_cometbls", "ok") -} - -func callPacket(cur realm, pair realcometbls.ChannelPair, receiverPath string) types.Packet { - call := z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(receiverPath), - ContractCalldata: []byte("calldata"), - } - return core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustCallInstruction(cross(cur), call)), types.Timestamp(0)) -} - -// Output: -// mock_calls 1 -// last_sender sender -// last_calldata calldata -// last_relayer_msg relay-msg -// receipt_after_recv true -// ack_after_recv true -// recv_call_dispatch_real_cometbls ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39b_recv_call_unregistered_receiver_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39b_recv_call_unregistered_receiver_filetest.gno deleted file mode 100644 index a174ab52..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39b_recv_call_unregistered_receiver_filetest.gno +++ /dev/null @@ -1,40 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const missingReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/missing" - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - packet := callPacket(cur, pair, missingReceiverPath) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, realcometbls.Z39MissingCallPacketCommitmentProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("receipt_after_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_recv", core.HasAcknowledgement(cross(cur), packet)) - println("recv_call_unregistered_real_cometbls", "ok") -} - -func callPacket(cur realm, pair realcometbls.ChannelPair, receiverPath string) types.Packet { - call := z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(receiverPath), - ContractCalldata: []byte("calldata"), - } - return core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustCallInstruction(cross(cur), call)), types.Timestamp(0)) -} - -// Output: -// receipt_after_recv true -// ack_after_recv true -// recv_call_unregistered_real_cometbls ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39c_recv_call_receiver_panic_only_maker_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39c_recv_call_receiver_panic_only_maker_filetest.gno deleted file mode 100644 index ffdde643..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z39c_recv_call_receiver_panic_only_maker_filetest.gno +++ /dev/null @@ -1,45 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func main(cur realm) { - impl.Register(cross(cur)) - mock.Reset(cross(cur)) - mock.SetPanic(cross(cur), "boom") - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - packet := callPacket(cur, pair, mockReceiverPath) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, realcometbls.Z39CallPacketCommitmentProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("mock_calls", mock.Calls(cross(cur))) - println("receipt_after_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_recv", core.HasAcknowledgement(cross(cur), packet)) - println("recv_call_panic_contained_real_cometbls", "ok") -} - -func callPacket(cur realm, pair realcometbls.ChannelPair, receiverPath string) types.Packet { - call := z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(receiverPath), - ContractCalldata: []byte("calldata"), - } - return core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustCallInstruction(cross(cur), call)), types.Timestamp(0)) -} - -// Output: -// mock_calls 1 -// receipt_after_recv true -// ack_after_recv true -// recv_call_panic_contained_real_cometbls ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40_fixture_inputs_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40_fixture_inputs_filetest.gno deleted file mode 100644 index d1c9946e..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40_fixture_inputs_filetest.gno +++ /dev/null @@ -1,79 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - "encoding/hex" - - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - core "gno.land/r/onbloc/ibc/union/core" -) - -const mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func main(cur realm) { - mixedPacket := z40MixedBatchPacket(cur) - panicPacket := z40PanicBatchPacket(cur) - mixedPacketKey := types.MustCommit(types.PacketCommitmentPath(mixedPacket)) - panicPacketKey := types.MustCommit(types.PacketCommitmentPath(panicPacket)) - packetValue := types.COMMITMENT_MAGIC - - printKV("mixed_batch_packet_commitment", mixedPacketKey[:], packetValue[:]) - printKV("panic_batch_packet_commitment", panicPacketKey[:], packetValue[:]) -} - -func z40MixedBatchPacket(cur realm) types.Packet { - return z40BatchPacket(cur, z.Batch{Instructions: []z.Instruction{ - e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(mockReceiverPath), - ContractCalldata: []byte("batch-call"), - }), - e2e.MustTokenOrderInstruction(cross(cur), z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte("ibc/batch-quote"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - }), - }}) -} - -func z40PanicBatchPacket(cur realm) types.Packet { - return z40BatchPacket(cur, z.Batch{Instructions: []z.Instruction{ - e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(mockReceiverPath), - ContractCalldata: []byte("panic-call"), - }), - e2e.MustTokenOrderInstruction(cross(cur), z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte("ibc/batch-panic-quote"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - }), - }}) -} - -func z40BatchPacket(cur realm, batch z.Batch) types.Packet { - return core.NewPacket(types.ChannelId(2), types.ChannelId(1), e2e.MustPacketData(cross(cur), e2e.MustBatchInstruction(cross(cur), batch)), types.Timestamp(0)) -} - -func printKV(name string, key []byte, value []byte) { - println(name+"_key", "0x"+hex.EncodeToString(key)) - println(name+"_value", "0x"+hex.EncodeToString(value)) -} - -// Output: -// mixed_batch_packet_commitment_key 0x5b6d15280476ff21b8582b241254a08073cd68019a7021427aa49ed2e12ed028 -// mixed_batch_packet_commitment_value 0x0100000000000000000000000000000000000000000000000000000000000000 -// panic_batch_packet_commitment_key 0x40b8521a5f940a9da33617a71e52dcf702f56c7f070333b94f23f5014b272e4a -// panic_batch_packet_commitment_value 0x0100000000000000000000000000000000000000000000000000000000000000 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40a_recv_batch_mixed_call_token_order_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40a_recv_batch_mixed_call_token_order_filetest.gno deleted file mode 100644 index 7e4bed98..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40a_recv_batch_mixed_call_token_order_filetest.gno +++ /dev/null @@ -1,81 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func main(cur realm) { - impl.Register(cross(cur)) - mock.Reset(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - packet := mixedBatchPacket(cur, pair, receiver) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{[]byte("batch-relay-msg")}, realcometbls.Z40MixedBatchPacketCommitmentProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("mock_calls", mock.Calls(cross(cur))) - println("last_calldata", mock.LastCalldata(cross(cur))) - println("last_relayer_msg", mock.LastRelayerMsg(cross(cur))) - println("quote_balance", impl.VoucherBalanceOf("ibc/batch-quote", address(receiver))) - println("receipt_after_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_recv", core.HasAcknowledgement(cross(cur), packet)) - println("ack_hash_matches_batch_ack", core.AcknowledgementHash(cross(cur), packet).String() == expectedAckHash(cur)) - println("recv_batch_mixed_real_cometbls", "ok") -} - -func mixedBatchPacket(cur realm, pair realcometbls.ChannelPair, receiver string) types.Packet { - batch := z.Batch{Instructions: []z.Instruction{ - e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(mockReceiverPath), - ContractCalldata: []byte("batch-call"), - }), - e2e.MustTokenOrderInstruction(cross(cur), z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte("ibc/batch-quote"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - }), - }} - return core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustBatchInstruction(cross(cur), batch)), types.Timestamp(0)) -} - -func expectedAckHash(cur realm) string { - ack := e2e.MustBatchAck(cross(cur), [][]byte{ - e2e.MustCallAck(cross(cur)), - universalErrorAck(), - }) - return types.CommitAcks([][]byte{ack}).String() -} - -func universalErrorAck() []byte { - ack, err := z.EncodeAck(z.Ack{Tag: u256.NewUint(0), InnerAck: []byte("UNIVERSAL_ERROR")}) - if err != nil { - panic(err) - } - return ack -} - -// Output: -// mock_calls 1 -// last_calldata batch-call -// last_relayer_msg batch-relay-msg -// quote_balance 0 -// receipt_after_recv true -// ack_after_recv true -// ack_hash_matches_batch_ack true -// recv_batch_mixed_real_cometbls ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40b_recv_batch_child_panic_only_maker_propagates_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40b_recv_batch_child_panic_only_maker_propagates_filetest.gno deleted file mode 100644 index f474a80d..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z40b_recv_batch_child_panic_only_maker_propagates_filetest.gno +++ /dev/null @@ -1,68 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const mockReceiverPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/mock" - -func main(cur realm) { - impl.Register(cross(cur)) - mock.Reset(cross(cur)) - mock.SetPanic(cross(cur), "boom") - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - receiver := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - packet := panicBatchPacket(cur, pair, receiver) - - core.PacketRecv(cross(cur), types.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, realcometbls.Z40PanicBatchPacketCommitmentProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("mock_calls", mock.Calls(cross(cur))) - println("quote_balance", impl.VoucherBalanceOf("ibc/batch-panic-quote", address(receiver))) - println("receipt_after_recv", core.HasPacketReceipt(cross(cur), packet)) - println("ack_after_recv", core.HasAcknowledgement(cross(cur), packet)) - println("ack_hash_matches_only_maker", core.AcknowledgementHash(cross(cur), packet).String() == onlyMakerAckHash()) - println("recv_batch_child_panic_real_cometbls", "ok") -} - -func panicBatchPacket(cur realm, pair realcometbls.ChannelPair, receiver string) types.Packet { - batch := z.Batch{Instructions: []z.Instruction{ - e2e.MustCallInstruction(cross(cur), z.Call{ - Sender: []byte("sender"), - ContractAddress: []byte(mockReceiverPath), - ContractCalldata: []byte("panic-call"), - }), - e2e.MustTokenOrderInstruction(cross(cur), z.TokenOrderV2{ - Sender: []byte("sender"), - Receiver: []byte(receiver), - BaseToken: []byte("ugnot"), - BaseAmount: u256.NewUint(100), - QuoteToken: []byte("ibc/batch-panic-quote"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_ESCROW, - }), - }} - return core.NewPacket(pair.Source, pair.Destination, e2e.MustPacketData(cross(cur), e2e.MustBatchInstruction(cross(cur), batch)), types.Timestamp(0)) -} - -func onlyMakerAckHash() string { - ack := make([]byte, len(z.ACK_ERR_ONLY_MAKER)) - copy(ack, z.ACK_ERR_ONLY_MAKER) - return types.CommitAcks([][]byte{ack}).String() -} - -// Output: -// mock_calls 1 -// quote_balance 0 -// receipt_after_recv true -// ack_after_recv true -// ack_hash_matches_only_maker true -// recv_batch_child_panic_real_cometbls ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42a_channel_open_ack_wrong_counterparty_id_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42a_channel_open_ack_wrong_counterparty_id_filetest.gno deleted file mode 100644 index 51110b3f..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42a_channel_open_ack_wrong_counterparty_id_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - clientId := realcometbls.CreateZ35CometBLSClient(cross(cur)) - connectionId := openConnection(cur, clientId, realcometbls.Z35ConnectionTryProof(cross(cur))) - core.ChannelOpenInit(cross(cur), types.NewMsgChannelOpenInit([]byte(zkgm.ProxyPkgPath()), []byte(zkgm.ProxyPkgPath()), connectionId, zkgm.Version, "g1msgrelayer")) - channelId := types.ChannelId(1) - - core.ChannelOpenAck(cross(cur), types.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(3), realcometbls.Z35ChannelTryProof(cross(cur)), uint64(realcometbls.DevnetHeight-1), "g1msgrelayer")) -} - -func openConnection(cur realm, clientId types.ClientId, proof []byte) types.ConnectionId { - connectionId := types.ConnectionId(1) - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), proof, uint64(realcometbls.DevnetHeight-1))) - return connectionId -} - -// Error: -// cometbls: membership verification failed: cometbls: membership proof verification failed: provided key doesn't match proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42b_channel_open_ack_wrong_version_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42b_channel_open_ack_wrong_version_filetest.gno deleted file mode 100644 index 8045e36b..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42b_channel_open_ack_wrong_version_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - clientId := realcometbls.CreateZ42WrongVersionCometBLSClient(cross(cur)) - connectionId := openConnection(cur, clientId, realcometbls.Z42WrongVersionConnectionTryProof(cross(cur))) - core.ChannelOpenInit(cross(cur), types.NewMsgChannelOpenInit([]byte(zkgm.ProxyPkgPath()), []byte(zkgm.ProxyPkgPath()), connectionId, zkgm.Version, "g1msgrelayer")) - channelId := types.ChannelId(1) - - core.ChannelOpenAck(cross(cur), types.NewMsgChannelOpenAck(channelId, "bad-version", types.ChannelId(2), realcometbls.Z42WrongVersionChannelTryProof(cross(cur)), uint64(realcometbls.DevnetHeight-1), "g1msgrelayer")) -} - -func openConnection(cur realm, clientId types.ClientId, proof []byte) types.ConnectionId { - connectionId := types.ConnectionId(1) - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), proof, uint64(realcometbls.DevnetHeight-1))) - return connectionId -} - -// Error: -// zkgm: unsupported channel version diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42c_connection_open_ack_wrong_counterparty_id_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42c_connection_open_ack_wrong_counterparty_id_filetest.gno deleted file mode 100644 index 90cc24f7..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42c_connection_open_ack_wrong_counterparty_id_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - clientId := realcometbls.CreateZ35CometBLSClient(cross(cur)) - connectionId := types.ConnectionId(1) - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(78), realcometbls.Z35ConnectionTryProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) -} - -// Error: -// cometbls: membership verification failed: cometbls: membership proof verification failed: provided key doesn't match proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42d_channel_open_ack_stale_state_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42d_channel_open_ack_stale_state_filetest.gno deleted file mode 100644 index 2d6f9aa8..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z42d_channel_open_ack_stale_state_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - clientId := realcometbls.CreateZ42StaleCometBLSClient(cross(cur)) - connectionId := openConnection(cur, clientId, realcometbls.Z42StaleConnectionTryProof(cross(cur))) - core.ChannelOpenInit(cross(cur), types.NewMsgChannelOpenInit([]byte(zkgm.ProxyPkgPath()), []byte(zkgm.ProxyPkgPath()), connectionId, zkgm.Version, "g1msgrelayer")) - channelId := types.ChannelId(1) - - core.ChannelOpenAck(cross(cur), types.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), realcometbls.Z42StaleChannelTryProof(cross(cur)), uint64(realcometbls.DevnetHeight-1), "g1msgrelayer")) -} - -func openConnection(cur realm, clientId types.ClientId, proof []byte) types.ConnectionId { - connectionId := types.ConnectionId(1) - core.ConnectionOpenInit(cross(cur), types.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) - core.ConnectionOpenAck(cross(cur), types.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), proof, uint64(realcometbls.DevnetHeight-1))) - return connectionId -} - -// Error: -// cometbls: membership verification failed: cometbls: membership proof verification failed: provided value doesn't match proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43a_verify_membership_empty_proof_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43a_verify_membership_empty_proof_filetest.gno deleted file mode 100644 index 406aff43..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43a_verify_membership_empty_proof_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - nil, - []byte("key"), - []byte("value"), - ) -} - -// Error: -// cometbls: membership verification failed: cometbls: proof count does not match spec count diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43b_verify_membership_proof_count_mismatch_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43b_verify_membership_proof_count_mismatch_filetest.gno deleted file mode 100644 index e564e825..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43b_verify_membership_proof_count_mismatch_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.OneExistenceProofStub(cross(cur)), - []byte("key"), - []byte("value"), - ) -} - -// Error: -// cometbls: membership verification failed: cometbls: proof count does not match spec count diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43d_verify_non_membership_first_proof_not_nonexistence_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43d_verify_non_membership_first_proof_not_nonexistence_filetest.gno deleted file mode 100644 index 4f2e7b37..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43d_verify_non_membership_first_proof_not_nonexistence_filetest.gno +++ /dev/null @@ -1,22 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyNonMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.TwoExistenceProofStubs(cross(cur)), - []byte("key"), - ) -} - -// Error: -// cometbls: non-membership verification failed: cometbls: first proof must be a non-existence proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43e_verify_membership_subroot_mismatch_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43e_verify_membership_subroot_mismatch_filetest.gno deleted file mode 100644 index 0add304a..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43e_verify_membership_subroot_mismatch_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateSyntheticCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticMembershipWrongSubrootProof(cross(cur)), - realcometbls.SyntheticMembershipKey(cross(cur)), - realcometbls.SyntheticMembershipValue(cross(cur)), - ) -} - -// Error: -// cometbls: membership verification failed: cometbls: membership proof verification failed: provided value doesn't match proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43f_verify_membership_malformed_proof_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43f_verify_membership_malformed_proof_filetest.gno deleted file mode 100644 index 29b558d9..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43f_verify_membership_malformed_proof_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - []byte{0x0a, 0xff}, - []byte("key"), - []byte("value"), - ) -} - -// Error: -// cometbls: invalid membership proof: proto: buffer underflow reading varint diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43g_verify_membership_final_root_mismatch_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43g_verify_membership_final_root_mismatch_filetest.gno deleted file mode 100644 index 75081bc1..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43g_verify_membership_final_root_mismatch_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticMembershipProof(cross(cur)), - realcometbls.SyntheticMembershipKey(cross(cur)), - realcometbls.SyntheticMembershipValue(cross(cur)), - ) -} - -// Error: -// cometbls: membership verification failed: cometbls: proof root does not match consensus state root diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43h_verify_membership_wrong_key_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43h_verify_membership_wrong_key_filetest.gno deleted file mode 100644 index 6846b3fb..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43h_verify_membership_wrong_key_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateSyntheticCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticMembershipProof(cross(cur)), - []byte("packet-key-wrong"), - realcometbls.SyntheticMembershipValue(cross(cur)), - ) -} - -// Error: -// cometbls: membership verification failed: cometbls: membership proof verification failed: provided key doesn't match proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43i_verify_membership_wrong_value_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43i_verify_membership_wrong_value_filetest.gno deleted file mode 100644 index 4e55b4bd..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z43i_verify_membership_wrong_value_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateSyntheticCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticMembershipProof(cross(cur)), - realcometbls.SyntheticMembershipKey(cross(cur)), - []byte("packet-value-wrong"), - ) -} - -// Error: -// cometbls: membership verification failed: cometbls: membership proof verification failed: provided value doesn't match proof diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44a_verify_membership_frozen_client_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44a_verify_membership_frozen_client_filetest.gno deleted file mode 100644 index 68a35e9d..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44a_verify_membership_frozen_client_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateFrozenSyntheticCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticMembershipProof(cross(cur)), - realcometbls.SyntheticMembershipKey(cross(cur)), - realcometbls.SyntheticMembershipValue(cross(cur)), - ) -} - -// Error: -// cometbls: client is Frozen diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44b_verify_membership_expired_client_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44b_verify_membership_expired_client_filetest.gno deleted file mode 100644 index c85e08a0..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44b_verify_membership_expired_client_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateExpiredSyntheticCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight-1)), - realcometbls.SyntheticMembershipProof(cross(cur)), - realcometbls.SyntheticMembershipKey(cross(cur)), - realcometbls.SyntheticMembershipValue(cross(cur)), - ) -} - -// Error: -// cometbls: client is Expired diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44c_verify_membership_missing_height_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44c_verify_membership_missing_height_filetest.gno deleted file mode 100644 index d002c36a..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios/z44c_verify_membership_missing_height_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios -package scenarios - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - realadapter "gno.land/r/onbloc/ibc/lightclients/cometbls" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" -) - -func main(cur realm) { - clientId := realcometbls.CreateRealCometBLSClient(cross(cur)) - realadapter.NewAdapter(cross(cur)).VerifyMembership( - clientId, - types.NewHeight(uint64(realcometbls.DevnetHeight)), - realcometbls.TwoExistenceProofStubs(cross(cur)), - []byte("key"), - []byte("value"), - ) -} - -// Error: -// cometbls: consensus state not found at height 3405691582 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/gnomod.toml deleted file mode 100644 index 299c189f..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios_batchsend" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/packet_lifecycle_fixture_inputs_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/packet_lifecycle_fixture_inputs_filetest.gno deleted file mode 100644 index eb13caab..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/packet_lifecycle_fixture_inputs_filetest.gno +++ /dev/null @@ -1,77 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios_batchsend -package scenarios_batchsend - -import ( - "encoding/hex" - - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - sender := string(testutils.TestAddress("timeout-sender")) - - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - BaseToken: []byte("ibc/base"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - destChannel, err := core.GetChannel(pair.Destination) - if err != nil { - panic(err) - } - packet := core.NewPacket(pair.Destination, destChannel.CounterpartyChannelId, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(3600)) - realcometbls.BatchSend(cross(cur), packet) - ack := e2e.MustSuccessAck(cross(cur), mustMarketMakerTokenOrderAck([]byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"))) - ackValue := types.CommitAcks([][]byte{ack}) - - ackKey := types.MustCommit(types.PacketAcknowledgementPath(packet)) - receiptKey := types.MustCommit(types.PacketAcknowledgementPath(packet)) - - printKV("ack_membership", ackKey[:], ackValue[:]) - println("ack_bytes", "0x"+hex.EncodeToString(ack)) - printKV("receipt_non_membership", receiptKey[:], nil) - println("source_channel", packet.SourceChannelId.String()) - println("destination_channel", packet.DestinationChannelId.String()) - println("packet_data", "0x"+hex.EncodeToString(packet.Data)) -} - -func mustMarketMakerTokenOrderAck(marketMaker []byte) []byte { - bz, err := z.EncodeTokenOrderAck(z.TokenOrderAck{ - FillType: new(u256.Uint).SetBytes(z.FILL_TYPE_MARKETMAKER[:]), - MarketMaker: marketMaker, - }) - if err != nil { - panic(err) - } - return bz -} - -func printKV(name string, key []byte, value []byte) { - println(name+"_key", "0x"+hex.EncodeToString(key)) - if value != nil { - println(name+"_value", "0x"+hex.EncodeToString(value)) - } -} - -// Output: -// ack_membership_key 0x3cde3b6891df12ae3a04f23e62738b1c7e209ddb5a5dd6ebc27b6c29cd539b18 -// ack_membership_value 0x015b3cd48177600c2efac9e26b978edfdf97f8480c0a7f3b0884f0b4817ed5a8 -// ack_bytes 0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000d1cec45e00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000028673177796d75343764726872306b7571323039386d3739326c797467746a326e797837377972736d000000000000000000000000000000000000000000000000 -// receipt_non_membership_key 0x3cde3b6891df12ae3a04f23e62738b1c7e209ddb5a5dd6ebc27b6c29cd539b18 -// source_channel 1 -// destination_channel 2 -// packet_data 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000002867317733356b366574307734367a36756d3964656a7832756a6c746130343768366c677263786d750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028673177796d75343764726872306b7571323039386d3739326c797467746a326e797837377972736d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086962632f62617365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000575676e6f740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z36_real_cometbls_ack_token_order_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z36_real_cometbls_ack_token_order_filetest.gno deleted file mode 100644 index bb5e9d56..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z36_real_cometbls_ack_token_order_filetest.gno +++ /dev/null @@ -1,65 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - sender := string(testutils.TestAddress("timeout-sender")) - - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - BaseToken: []byte("ibc/base"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - destChannel, err := core.GetChannel(pair.Destination) - if err != nil { - panic(err) - } - packet := core.NewPacket(pair.Destination, destChannel.CounterpartyChannelId, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(3600)) - realcometbls.BatchSend(cross(cur), packet) - marketMaker := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - ack := e2e.MustSuccessAck(cross(cur), mustMarketMakerTokenOrderAck([]byte(marketMaker))) - - println("commitment_before_ack", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_balance_before_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - - core.PacketAcknowledgement(cross(cur), types.NewMsgPacketAcknowledgement([]types.Packet{packet}, [][]byte{ack}, realcometbls.Z36AckMembershipProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("commitment_after_ack", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_balance_after_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - println("ack_real_cometbls", "ok") -} - -func mustMarketMakerTokenOrderAck(marketMaker []byte) []byte { - bz, err := z.EncodeTokenOrderAck(z.TokenOrderAck{ - FillType: new(u256.Uint).SetBytes(z.FILL_TYPE_MARKETMAKER[:]), - MarketMaker: marketMaker, - }) - if err != nil { - panic(err) - } - return bz -} - -// Output: -// commitment_before_ack true -// market_maker_balance_before_ack 0 -// commitment_after_ack false -// market_maker_balance_after_ack 21 -// ack_real_cometbls ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z37_real_cometbls_timeout_non_membership_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z37_real_cometbls_timeout_non_membership_filetest.gno deleted file mode 100644 index f6a3d67c..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z37_real_cometbls_timeout_non_membership_filetest.gno +++ /dev/null @@ -1,52 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ37CometBLSChannel(cross(cur)) - sender := string(testutils.TestAddress("timeout-sender")) - - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - BaseToken: []byte("ibc/base"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - destChannel, err := core.GetChannel(pair.Destination) - if err != nil { - panic(err) - } - packet := core.NewPacket(pair.Destination, destChannel.CounterpartyChannelId, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(3600)) - realcometbls.BatchSend(cross(cur), packet) - - println("commitment_before_timeout", core.HasPacketCommitment(cross(cur), packet)) - println("sender_balance_before_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(sender))) - - core.PacketTimeout(cross(cur), types.NewMsgPacketTimeout(packet, realcometbls.Z37ReceiptNonMembershipProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("commitment_after_timeout", core.HasPacketCommitment(cross(cur), packet)) - println("sender_balance_after_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(sender))) - println("timeout_real_cometbls", "ok") -} - -// Output: -// commitment_before_timeout true -// sender_balance_before_timeout 0 -// commitment_after_timeout false -// sender_balance_after_timeout 21 -// timeout_real_cometbls ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z38b_ack_double_ack_noop_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z38b_ack_double_ack_noop_filetest.gno deleted file mode 100644 index a98e97ed..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z38b_ack_double_ack_noop_filetest.gno +++ /dev/null @@ -1,66 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - sender := string(testutils.TestAddress("timeout-sender")) - - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - BaseToken: []byte("ibc/base"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - destChannel, err := core.GetChannel(pair.Destination) - if err != nil { - panic(err) - } - packet := core.NewPacket(pair.Destination, destChannel.CounterpartyChannelId, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(3600)) - realcometbls.BatchSend(cross(cur), packet) - marketMaker := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - ack := e2e.MustSuccessAck(cross(cur), mustMarketMakerTokenOrderAck([]byte(marketMaker))) - msg := types.NewMsgPacketAcknowledgement([]types.Packet{packet}, [][]byte{ack}, realcometbls.Z36AckMembershipProof(cross(cur)), uint64(realcometbls.DevnetHeight-1)) - - core.PacketAcknowledgement(cross(cur), msg) - println("commitment_after_first_ack", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_balance_after_first_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - - core.PacketAcknowledgement(cross(cur), msg) - println("commitment_after_second_ack", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_balance_after_second_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - println("double_ack_noop", "ok") -} - -func mustMarketMakerTokenOrderAck(marketMaker []byte) []byte { - bz, err := z.EncodeTokenOrderAck(z.TokenOrderAck{ - FillType: new(u256.Uint).SetBytes(z.FILL_TYPE_MARKETMAKER[:]), - MarketMaker: marketMaker, - }) - if err != nil { - panic(err) - } - return bz -} - -// Output: -// commitment_after_first_ack false -// market_maker_balance_after_first_ack 21 -// commitment_after_second_ack false -// market_maker_balance_after_second_ack 21 -// double_ack_noop ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z38c_timeout_after_ack_noop_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z38c_timeout_after_ack_noop_filetest.gno deleted file mode 100644 index 53d85c4b..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/realcometbls/scenarios_batchsend/z38c_timeout_after_ack_noop_filetest.gno +++ /dev/null @@ -1,71 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls/scenarios_batchsend -package scenarios_batchsend - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - realcometbls "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/realcometbls" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - impl.Register(cross(cur)) - pair := realcometbls.OpenZ35CometBLSChannel(cross(cur)) - sender := string(testutils.TestAddress("timeout-sender")) - - order := z.TokenOrderV2{ - Sender: []byte(sender), - Receiver: []byte("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - BaseToken: []byte("ibc/base"), - BaseAmount: u256.NewUint(21), - QuoteToken: []byte("ugnot"), - QuoteAmount: u256.NewUint(21), - Kind: z.TOKEN_ORDER_KIND_UNESCROW, - } - destChannel, err := core.GetChannel(pair.Destination) - if err != nil { - panic(err) - } - packet := core.NewPacket(pair.Destination, destChannel.CounterpartyChannelId, e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)), types.Timestamp(3600)) - realcometbls.BatchSend(cross(cur), packet) - marketMaker := "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" - ack := e2e.MustSuccessAck(cross(cur), mustMarketMakerTokenOrderAck([]byte(marketMaker))) - - core.PacketAcknowledgement(cross(cur), types.NewMsgPacketAcknowledgement([]types.Packet{packet}, [][]byte{ack}, realcometbls.Z36AckMembershipProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("commitment_after_ack", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_balance_after_ack", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - println("sender_balance_before_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(sender))) - - core.PacketTimeout(cross(cur), types.NewMsgPacketTimeout(packet, realcometbls.Z37ReceiptNonMembershipProof(cross(cur)), uint64(realcometbls.DevnetHeight-1))) - - println("commitment_after_timeout", core.HasPacketCommitment(cross(cur), packet)) - println("market_maker_balance_after_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(marketMaker))) - println("sender_balance_after_timeout", impl.VoucherBalanceOf(string(order.BaseToken), address(sender))) - println("timeout_after_ack_noop", "ok") -} - -func mustMarketMakerTokenOrderAck(marketMaker []byte) []byte { - bz, err := z.EncodeTokenOrderAck(z.TokenOrderAck{ - FillType: new(u256.Uint).SetBytes(z.FILL_TYPE_MARKETMAKER[:]), - MarketMaker: marketMaker, - }) - if err != nil { - panic(err) - } - return bz -} - -// Output: -// commitment_after_ack false -// market_maker_balance_after_ack 21 -// sender_balance_before_timeout 0 -// commitment_after_timeout false -// market_maker_balance_after_timeout 21 -// sender_balance_after_timeout 0 -// timeout_after_ack_noop ok diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/scenariohelpers/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/scenariohelpers/gnomod.toml deleted file mode 100644 index 60f46be3..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/scenariohelpers/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/scenariohelpers" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/scenariohelpers/helpers.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/scenariohelpers/helpers.gno deleted file mode 100644 index 2da20d36..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/scenariohelpers/helpers.gno +++ /dev/null @@ -1,73 +0,0 @@ -package scenariohelpers - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - "gno.land/p/nt/testutils/v0" - z "gno.land/p/onbloc/ibc/union/zkgm" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - e2e "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/e2e" - impl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" - core "gno.land/r/onbloc/ibc/union/core" -) - -const ( - ScenarioImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" -) - -func NewV1Harness(cur realm) zkgm.IApp { - return impl.NewUCS03ZkgmV1(zkgm.Store()) -} - -func RegisterV1(cur realm) { - impl.Register(cross(cur)) -} - -func InstallV1Harness(cur realm) zkgm.IApp { - inst := NewV1Harness(cross(cur)) - RegisterV1(cross(cur)) - - return inst -} - -func DecodeTokenMetadata(bz []byte) z.TokenMetadata { - meta, err := z.DecodeTokenMetadata(bz) - if err != nil { - panic(err) - } - - return meta -} - -func TokenOrderPacketData(cur realm, order z.TokenOrderV2) []byte { - return e2e.MustPacketData(cross(cur), e2e.MustTokenOrderInstruction(cross(cur), order)) -} - -func ChannelBalanceStr(channelId types.ChannelId, path *u256.Uint, baseToken []byte, quoteToken []byte) string { - balance, ok := zkgm.Store().GetChannelBalanceV2(impl.ChannelBalanceKeyV2(channelId, path, baseToken, quoteToken)) - if !ok || balance == nil { - return "0" - } - - return balance.ToString() -} - -func MintVoucher(cur realm, inst zkgm.IApp, channelId types.ChannelId, base string, receiver string, amount uint64, symbol string) string { - meta := e2e.MustTokenMetadata(cross(cur), "grc20", z.TokenInitializer{Name: base, Symbol: symbol, Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte(base), z.MetadataImage(DecodeTokenMetadata(meta))) - order := z.TokenOrderV2{ - Sender: []byte("remote"), - Receiver: []byte(receiver), - BaseToken: []byte(base), - BaseAmount: u256.NewUint(amount), - QuoteToken: []byte(quoteToken), - QuoteAmount: u256.NewUint(amount), - Kind: z.TOKEN_ORDER_KIND_INITIALIZE, - Metadata: meta, - } - packet := core.NewPacket(types.ChannelId(1), channelId, TokenOrderPacketData(cross(cur), order), types.Timestamp(100)) - inst.OnRecvPacket(0, cur, packet, testutils.TestAddress("scenario-relayer"), nil) - - return quoteToken -} diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/gnomod.toml deleted file mode 100644 index bfa2290e..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs31_impl_upgrade_continuity_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs31_impl_upgrade_continuity_filetest.gno deleted file mode 100644 index 8fcc1c7e..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs31_impl_upgrade_continuity_filetest.gno +++ /dev/null @@ -1,56 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import ( - stdtesting "testing" - - u256 "gno.land/p/gnoswap/uint256" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - upgradeimpl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" -) - -func main(cur realm) { - oldImpl := zkgm.ProxyPkgPath() + "/testing/upgrade-old" - newImpl := zkgm.ProxyPkgPath() + "/testing/upgrade-new" - balanceKey := "upgrade-continuity/channel-balance" - voucherDenom := "ibc/upgrade-continuity" - voucherHolder := address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") - - println("[SCENARIO] 1. bootstrap old implementation") - stdtesting.SetRealm(stdtesting.NewCodeRealm(oldImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "before"), []string{ - oldImpl, - newImpl, - upgradeimpl.PkgPath(), - })) - zkgm.SetChannelBalanceV2(cross(cur), balanceKey, u256.NewUint(40)) - upgradeimpl.MintVoucher(cross(cur), voucherDenom, voucherHolder, u256.NewUint(17)) - println("[EXPECTED] impl_path_before", zkgm.ImplPath()) - println("[EXPECTED] render_before", zkgm.Render("")) - - println("") - println("[SCENARIO] 2. upgrade through allowed implementation") - stdtesting.SetRealm(stdtesting.NewCodeRealm(newImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "after"), []string{ - newImpl, - })) - println("[EXPECTED] impl_path_after", zkgm.ImplPath()) - println("[EXPECTED] render_after", zkgm.Render("")) - println("[EXPECTED] channel_balance_after", zkgm.GetChannelBalanceV2(balanceKey).Dec()) - println("[EXPECTED] voucher_balance_after", zkgm.VoucherBalanceOf(voucherDenom, voucherHolder)) - println("[EXPECTED] old_impl_allowed", zkgm.InAllowedImpls(oldImpl)) - println("[EXPECTED] new_impl_allowed", zkgm.InAllowedImpls(newImpl)) -} - -// Output: -// [SCENARIO] 1. bootstrap old implementation -// [EXPECTED] impl_path_before gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade-old -// [EXPECTED] render_before before -// -// [SCENARIO] 2. upgrade through allowed implementation -// [EXPECTED] impl_path_after gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade-new -// [EXPECTED] render_after after -// [EXPECTED] channel_balance_after 40 -// [EXPECTED] voucher_balance_after 17 -// [EXPECTED] old_impl_allowed false -// [EXPECTED] new_impl_allowed true diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_allowed_impl_upgrade_path_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_allowed_impl_upgrade_path_filetest.gno deleted file mode 100644 index 7e0cd849..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_allowed_impl_upgrade_path_filetest.gno +++ /dev/null @@ -1,45 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import ( - stdtesting "testing" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - upgradeimpl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" -) - -func main(cur realm) { - oldImpl := zkgm.ProxyPkgPath() + "/testing/allowed-old" - newImpl := zkgm.ProxyPkgPath() + "/testing/allowed-new" - - println("[SCENARIO] 1. bootstrap with next implementation allowlisted") - stdtesting.SetRealm(stdtesting.NewCodeRealm(oldImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "old"), []string{ - oldImpl, - newImpl, - })) - println("[EXPECTED] old_impl_path", zkgm.ImplPath()) - println("[EXPECTED] new_impl_allowed_before", zkgm.InAllowedImpls(newImpl)) - - println("") - println("[SCENARIO] 2. allowed implementation self-registers") - stdtesting.SetRealm(stdtesting.NewCodeRealm(newImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "new"), []string{ - newImpl, - })) - println("[EXPECTED] new_impl_path", zkgm.ImplPath()) - println("[EXPECTED] old_impl_allowed_after", zkgm.InAllowedImpls(oldImpl)) - println("[EXPECTED] new_impl_allowed_after", zkgm.InAllowedImpls(newImpl)) - println("[EXPECTED] render_after", zkgm.Render("")) -} - -// Output: -// [SCENARIO] 1. bootstrap with next implementation allowlisted -// [EXPECTED] old_impl_path gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/allowed-old -// [EXPECTED] new_impl_allowed_before true -// -// [SCENARIO] 2. allowed implementation self-registers -// [EXPECTED] new_impl_path gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/allowed-new -// [EXPECTED] old_impl_allowed_after false -// [EXPECTED] new_impl_allowed_after true -// [EXPECTED] render_after new diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_removed_allowed_impl_rejected_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_removed_allowed_impl_rejected_filetest.gno deleted file mode 100644 index 894aa782..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_removed_allowed_impl_rejected_filetest.gno +++ /dev/null @@ -1,28 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import ( - stdtesting "testing" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - upgradeimpl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" -) - -func main(cur realm) { - currentImpl := zkgm.ProxyPkgPath() + "/testing/current" - candidate := zkgm.ProxyPkgPath() + "/testing/candidate" - - stdtesting.SetRealm(stdtesting.NewCodeRealm(currentImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "current"), []string{ - candidate, - })) - - stdtesting.SetRealm(stdtesting.NewCodeRealm(candidate)) - // Intentionally pass a non-nil empty allowlist: this clears allowedImpls, - // removing candidate's own upgrade authority before the next call. - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), nil, []string{})) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "removed"), nil)) -} - -// Error: -// permission denied for prev realm: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/candidate diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_unallowed_impl_rejected_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_unallowed_impl_rejected_filetest.gno deleted file mode 100644 index ce5b5b5b..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs32_unallowed_impl_rejected_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import ( - stdtesting "testing" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - upgradeimpl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" -) - -func main(cur realm) { - currentImpl := zkgm.ProxyPkgPath() + "/testing/current" - - stdtesting.SetRealm(stdtesting.NewCodeRealm(currentImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "current"), []string{ - currentImpl, - })) - - stdtesting.SetRealm(stdtesting.NewCodeRealm(zkgm.ProxyPkgPath() + "/testing/not-allowed")) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "denied"), nil)) -} - -// Error: -// permission denied for prev realm: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/not-allowed diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_bootstrap_nil_impl_rejected_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_bootstrap_nil_impl_rejected_filetest.gno deleted file mode 100644 index bb995de0..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_bootstrap_nil_impl_rejected_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - -func main(cur realm) { - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), nil, []string{ - zkgm.ProxyPkgPath() + "/v0/impl", - })) -} - -// Error: -// zkgm: bootstrap UpdateImpl must install an impl diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_bootstrap_outside_namespace_rejected_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_bootstrap_outside_namespace_rejected_filetest.gno deleted file mode 100644 index 98a7d250..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_bootstrap_outside_namespace_rejected_filetest.gno +++ /dev/null @@ -1,19 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import ( - stdtesting "testing" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - upgradeimpl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" -) - -func main(cur realm) { - stdtesting.SetRealm(stdtesting.NewCodeRealm("gno.land/r/not-onbloc/unionibc/v1/apps/zkgm/v0/loader")) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "outside"), []string{ - zkgm.ProxyPkgPath() + "/v0/impl", - })) -} - -// Error: -// zkgm: bootstrap not permitted for caller: gno.land/r/not-onbloc/unionibc/v1/apps/zkgm/v0/loader diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_prod_impl_empty_allowed_bootstrap_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_prod_impl_empty_allowed_bootstrap_filetest.gno deleted file mode 100644 index e7ac1a9c..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs33_prod_impl_empty_allowed_bootstrap_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import ( - stdtesting "testing" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - upgradeimpl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" -) - -func main(cur realm) { - stdtesting.SetRealm(stdtesting.NewCodeRealm(zkgm.ProductionImplPath())) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "prod-impl"), []string{})) - - println("bootstrapped", zkgm.Bootstrapped()) - println("impl_path", zkgm.ImplPath()) - println("allowed_count", len(zkgm.AllowedImpls())) -} - -// Output: -// bootstrapped true -// impl_path gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1 -// allowed_count 0 diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs36_inflight_completion_after_upgrade_filetest.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs36_inflight_completion_after_upgrade_filetest.gno deleted file mode 100644 index 4524709c..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgrade/zs36_inflight_completion_after_upgrade_filetest.gno +++ /dev/null @@ -1,58 +0,0 @@ -// PKGPATH: gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgrade -package upgrade - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - stdtesting "testing" - - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - upgradeimpl "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" - core "gno.land/r/onbloc/ibc/union/core" -) - -func main(cur realm) { - oldImpl := zkgm.ProxyPkgPath() + "/testing/inflight-old" - newImpl := zkgm.ProxyPkgPath() + "/testing/inflight-new" - parent := core.NewPacket(types.ChannelId(10), types.ChannelId(11), []byte("parent"), types.Timestamp(100)) - child := core.NewPacket(types.ChannelId(12), types.ChannelId(13), []byte("child"), types.Timestamp(200)) - key := zkgm.NewInFlightKey(cross(cur), types.MustCommit(types.CommitPacket(child))) - value := zkgm.NewInFlightValue(cross(cur), parent) - - println("[SCENARIO] 1. record in-flight packet before upgrade") - stdtesting.SetRealm(stdtesting.NewCodeRealm(oldImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "old"), []string{ - oldImpl, - newImpl, - })) - zkgm.SetInFlightPacket(cross(cur), key, value) - println("[EXPECTED] impl_path_before", zkgm.ImplPath()) - - println("") - println("[SCENARIO] 2. upgrade implementation") - stdtesting.SetRealm(stdtesting.NewCodeRealm(newImpl)) - zkgm.UpdateImpl(cross(cur), zkgm.NewUpdateRequest(cross(cur), upgradeimpl.New(cross(cur), "new"), []string{ - newImpl, - })) - println("[EXPECTED] impl_path_after", zkgm.ImplPath()) - - println("") - println("[SCENARIO] 3. complete in-flight packet after upgrade") - popped, popFound := zkgm.PopInFlightPacket(cross(cur), key) - _, foundAgain := zkgm.PopInFlightPacket(cross(cur), key) - println("[EXPECTED] pop_after_upgrade", popFound) - println("[EXPECTED] parent_data", string(popped.ParentPacket.Data)) - println("[EXPECTED] second_pop", foundAgain) -} - -// Output: -// [SCENARIO] 1. record in-flight packet before upgrade -// [EXPECTED] impl_path_before gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/inflight-old -// -// [SCENARIO] 2. upgrade implementation -// [EXPECTED] impl_path_after gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/inflight-new -// -// [SCENARIO] 3. complete in-flight packet after upgrade -// [EXPECTED] pop_after_upgrade true -// [EXPECTED] parent_data parent -// [EXPECTED] second_pop false diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgradeimpl/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgradeimpl/gnomod.toml deleted file mode 100644 index f131811d..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgradeimpl/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgradeimpl/impl.gno b/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgradeimpl/impl.gno deleted file mode 100644 index 99cb2193..00000000 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/upgradeimpl/impl.gno +++ /dev/null @@ -1,62 +0,0 @@ -package upgradeimpl - -import ( - types "gno.land/p/onbloc/ibc/union/types" - - u256 "gno.land/p/gnoswap/uint256" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" - core "gno.land/r/onbloc/ibc/union/core" -) - -const pkgPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/testing/upgradeimpl" - -type Impl struct { - label string -} - -func New(cur realm, label string) zkgm.ZkgmImpl { - return &Impl{label: label} -} - -func PkgPath() string { - return pkgPath -} - -func MintVoucher(cur realm, ibcDenom string, receiver address, amount *u256.Uint) { - if err := zkgm.MintVoucher(cross(cur), ibcDenom, ibcDenom, [32]byte{}, "", "UPGRADE", 0, receiver.String(), amount); err != nil { - panic(err) - } -} - -func (i *Impl) PreChannelOpenInit(cur realm, channelId types.ChannelId) {} - -func (i *Impl) PreChannelOpenTry(cur realm, channelId types.ChannelId, counterpartyVersion string) {} - -func (i *Impl) PostChannelOpenAck(cur realm, channelId types.ChannelId, counterpartyChannelId types.ChannelId) { -} - -func (i *Impl) PostChannelOpenConfirm(cur realm, channelId types.ChannelId) {} - -func (i *Impl) PreChannelCloseInit(cur realm, channelId types.ChannelId) {} - -func (i *Impl) PostChannelCloseConfirm(cur realm, channelId types.ChannelId) {} - -func (i *Impl) Recv(cur realm, packet types.Packet, relayer address, relayerMsg []byte) types.RecvPacketResult { - return core.NewRecvPacketResult(types.PacketStatusSuccess, []byte(i.label)) -} - -func (i *Impl) IntentRecv(cur realm, packet types.Packet, marketMaker address, marketMakerMsg []byte) types.RecvPacketResult { - return core.NewRecvPacketResult(types.PacketStatusSuccess, []byte(i.label)) -} - -func (i *Impl) Ack(cur realm, packet types.Packet, ack []byte, relayer address) {} - -func (i *Impl) Timeout(cur realm, packet types.Packet, relayer address) {} - -func (i *Impl) Send(cur realm, req zkgm.SendRequest) ([]byte, error) { - return []byte(i.label), nil -} - -func (i *Impl) Render(pkgpath string, path string) string { - return i.label -} diff --git a/gno.land/r/onbloc/ibc/scenario/union/access/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/access/gnomod.toml new file mode 100644 index 00000000..960f3464 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/access/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/access" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/access/grant_relayer_role_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/access/grant_relayer_role_filetest.gno new file mode 100644 index 00000000..7b6f68e2 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/access/grant_relayer_role_filetest.gno @@ -0,0 +1,73 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/access +package access + +// grant_relayer_role_filetest is the NORMAL-path access scenario. The baked-in +// admin (DefaultAdminAddress, which holds AdminRole from the access realm's init) +// grants the RELAYER role to a fresh account. The account moves from unauthorized +// to authorized for the relayer-gated core selectors — verified as a before/after +// authorization diff, the access-control analogue of a balance diff. + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + + "gno.land/p/onbloc/access/manager" + types "gno.land/p/onbloc/ibc/union/types" + + "gno.land/r/onbloc/ibc/union/access" +) + +const ( + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // baked-in DefaultAdminAddress (holds AdminRole) + relayerAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Genesis: admin holds AdminRole, relayer account holds nothing") + showAuthorization() + println("[EXPECTED] relayer should NOT be authorized yet (no RelayerRole)") + println("") + + println("[SCENARIO] 2. Admin grants the RELAYER role to the relayer account") + grantRelayer(cur) + println("") + + println("[SCENARIO] 3. Relayer is now authorized for relayer-gated core selectors") + showAuthorization() + println("[EXPECTED] relayer should now be authorized (RelayerRole maps to relayer selectors)") +} + +// grantRelayer grants RELAYER to relayerAddr as the admin. Admin authorizes via +// cur.Previous(), so SetRealm(admin) and the cross(cur) call share this frame. +func grantRelayer(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + newMember := access.GrantRole(cross(cur), access.RelayerRole, relayerAddr) + ufmt.Printf("[INFO] GrantRole returned newMember=%t\n", newMember) + ufmt.Println("[EXPECTED] newMember should be true (first grant)") +} + +// showAuthorization reads (non-crossing) the current role membership and the derived +// authorization for a relayer-gated selector on the core realm. +func showAuthorization() { + ufmt.Printf("[INFO] admin has AdminRole: %t\n", access.HasRole(manager.AdminRole, adminAddr).IsMember) + ufmt.Printf("[INFO] relayer has RelayerRole: %t\n", access.HasRole(access.RelayerRole, relayerAddr).IsMember) + ufmt.Printf("[INFO] relayer authorized for packet_recv on core: %t\n", access.IsAuthorized(access.CoreRealmPath, types.RelayerSelectorPacketRecv, relayerAddr)) +} + +// Output: +// [SCENARIO] 1. Genesis: admin holds AdminRole, relayer account holds nothing +// [INFO] admin has AdminRole: true +// [INFO] relayer has RelayerRole: false +// [INFO] relayer authorized for packet_recv on core: false +// [EXPECTED] relayer should NOT be authorized yet (no RelayerRole) +// +// [SCENARIO] 2. Admin grants the RELAYER role to the relayer account +// [INFO] GrantRole returned newMember=true +// [EXPECTED] newMember should be true (first grant) +// +// [SCENARIO] 3. Relayer is now authorized for relayer-gated core selectors +// [INFO] admin has AdminRole: true +// [INFO] relayer has RelayerRole: true +// [INFO] relayer authorized for packet_recv on core: true +// [EXPECTED] relayer should now be authorized (RelayerRole maps to relayer selectors) diff --git a/gno.land/r/onbloc/ibc/scenario/union/access/reject_unauthorized_grant_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/access/reject_unauthorized_grant_filetest.gno new file mode 100644 index 00000000..e00693e8 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/access/reject_unauthorized_grant_filetest.gno @@ -0,0 +1,42 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/access +package access + +// reject_unauthorized_grant_filetest is the EXCEPTION-path access scenario. Only +// the admin of a role may grant it; a non-admin account is not an admin of +// RelayerRole, so its grant attempt is rejected. The rejection is the terminating +// panic of main, matched by the // Error: directive (the repo's convention for +// expected-panic filetests — recover does not catch panics across cross(cur)). + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + + "gno.land/r/onbloc/ibc/union/access" +) + +const ( + relayerAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") + nonAdminAddr = address("g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu") // holds no role +) + +func main(cur realm) { + println("[SCENARIO] 1. A non-admin account cannot administer RelayerRole") + ufmt.Printf("[INFO] non-admin can admin RelayerRole: %t\n", access.CanAdminRole(access.RelayerRole, nonAdminAddr).Immediate) + ufmt.Println("[EXPECTED] non-admin should NOT be able to administer RelayerRole") + println("") + + println("[SCENARIO] 2. The non-admin attempts to grant RELAYER -> rejected") + testing.SetRealm(testing.NewUserRealm(nonAdminAddr)) + access.GrantRole(cross(cur), access.RelayerRole, relayerAddr) +} + +// Output: +// [SCENARIO] 1. A non-admin account cannot administer RelayerRole +// [INFO] non-admin can admin RelayerRole: false +// [EXPECTED] non-admin should NOT be able to administer RelayerRole +// +// [SCENARIO] 2. The non-admin attempts to grant RELAYER -> rejected + +// Error: +// access manager unauthorized account: g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu must have role 0 diff --git a/gno.land/r/onbloc/ibc/scenario/union/access/role_lifecycle_by_operation_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/access/role_lifecycle_by_operation_filetest.gno new file mode 100644 index 00000000..4f2021a5 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/access/role_lifecycle_by_operation_filetest.gno @@ -0,0 +1,77 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/access +package access + +// role_lifecycle_by_operation_filetest is the BY-TYPE access scenario. It walks the +// three distinct role-membership operations — GRANT (admin adds), REVOKE (admin +// removes), RENOUNCE (member removes itself) — and after each one reports the +// member's RelayerRole membership so every transition is verified as a diff. + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + + "gno.land/r/onbloc/ibc/union/access" +) + +const ( + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // baked-in admin (AdminRole) + memberAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. GRANT: admin adds RELAYER to the member") + grant(cur) + report("after grant") + println("[EXPECTED] member should now hold RelayerRole") + println("") + + println("[SCENARIO] 2. REVOKE: admin removes RELAYER from the member") + revoke(cur) + report("after revoke") + println("[EXPECTED] member should no longer hold RelayerRole") + println("") + + println("[SCENARIO] 3. RENOUNCE: member is re-granted, then drops RELAYER itself") + grant(cur) + renounce(cur) + report("after renounce") + println("[EXPECTED] member should no longer hold RelayerRole (self-renounced)") +} + +func grant(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + ufmt.Printf("[INFO] GrantRole newMember=%t\n", access.GrantRole(cross(cur), access.RelayerRole, memberAddr)) +} + +func revoke(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + ufmt.Printf("[INFO] RevokeRole revoked=%t\n", access.RevokeRole(cross(cur), access.RelayerRole, memberAddr)) +} + +// renounce is driven by the member itself, confirming with its own address. +func renounce(cur realm) { + testing.SetRealm(testing.NewUserRealm(memberAddr)) + ufmt.Printf("[INFO] RenounceRole revoked=%t\n", access.RenounceRole(cross(cur), access.RelayerRole, memberAddr)) +} + +func report(label string) { + ufmt.Printf("[INFO] member has RelayerRole %s: %t\n", label, access.HasRole(access.RelayerRole, memberAddr).IsMember) +} + +// Output: +// [SCENARIO] 1. GRANT: admin adds RELAYER to the member +// [INFO] GrantRole newMember=true +// [INFO] member has RelayerRole after grant: true +// [EXPECTED] member should now hold RelayerRole +// +// [SCENARIO] 2. REVOKE: admin removes RELAYER from the member +// [INFO] RevokeRole revoked=true +// [INFO] member has RelayerRole after revoke: false +// [EXPECTED] member should no longer hold RelayerRole +// +// [SCENARIO] 3. RENOUNCE: member is re-granted, then drops RELAYER itself +// [INFO] GrantRole newMember=true +// [INFO] RenounceRole revoked=true +// [INFO] member has RelayerRole after renounce: false +// [EXPECTED] member should no longer hold RelayerRole (self-renounced) diff --git a/gno.land/r/onbloc/ibc/scenario/union/app/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/app/gnomod.toml new file mode 100644 index 00000000..7344718e --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/app/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/app" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/app/register_app_and_route_handshake_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/app/register_app_and_route_handshake_filetest.gno new file mode 100644 index 00000000..632e1587 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/app/register_app_and_route_handshake_filetest.gno @@ -0,0 +1,150 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/app +package app + +// register_app_and_route_handshake_filetest is the NORMAL-path app scenario. It +// registers the zkgm app at its port (HasApp false -> true), then drives a channel +// handshake to that port. Core routes the OnChannelOpenInit / OnChannelOpenAck +// callbacks to the registered app, advancing the channel Init -> Open — verified as +// a channel-state diff. + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + "gno.land/p/onbloc/ibc/union/lightclient" + types "gno.land/p/onbloc/ibc/union/types" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + mockClientType = types.ClientType("scenario-mock-lc") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap core+zkgm and open a client/connection (app not yet registered)") + connectionId := bootstrap(cur) + ufmt.Printf("[INFO] app bound at zkgm port: %t\n", core.HasApp([]byte(zkgm.ProxyPkgPath()))) + ufmt.Println("[EXPECTED] no app should be bound at the port yet") + println("") + + println("[SCENARIO] 2. Register the zkgm app at its port") + testing.SetRealm(testing.NewUserRealm(adminAddr)) + zkgm.RegisterCoreApp(cross(cur)) + ufmt.Printf("[INFO] app bound at zkgm port: %t\n", core.HasApp([]byte(zkgm.ProxyPkgPath()))) + ufmt.Println("[EXPECTED] the zkgm app should now be bound") + println("") + + println("[SCENARIO] 3. Channel handshake routes OnChannelOpenInit/Ack to the app (Init -> Open)") + openChannel(cur, connectionId) +} + +// bootstrap installs the impls, grants the relayer role, and opens a mock-backed +// client and connection. It stops short of registering the app or opening a channel. +func bootstrap(cur realm) types.ConnectionId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + + core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { + return &mockLightClient{}, nil + }) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + return connectionId +} + +// openChannel drives the Init and Ack handshake legs and reports the channel state +// after each, proving the app received the routed callbacks. +func openChannel(cur realm, connectionId types.ConnectionId) { + portId := []byte(zkgm.ProxyPkgPath()) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + reportChannel(channelId, "after OpenInit") + + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + reportChannel(channelId, "after OpenAck") + ufmt.Println("[EXPECTED] channel should advance Init -> Open as the app handles each handshake leg") +} + +func reportChannel(channelId types.ChannelId, label string) { + ch, err := core.GetChannel(channelId) + if err != nil { + ufmt.Printf("[INFO] channel %s %s: \n", channelId.String(), label) + return + } + ufmt.Printf("[INFO] channel %s %s: state=%s\n", channelId.String(), label, channelStateLabel(ch.State)) +} + +func channelStateLabel(s types.ChannelState) string { + switch s { + case types.ChannelStateInit: + return "Init" + case types.ChannelStateTryOpen: + return "TryOpen" + case types.ChannelStateOpen: + return "Open" + case types.ChannelStateClosed: + return "Closed" + default: + return "Unknown" + } +} + +// --- permissive mock light client (accepts any proof) --- + +type mockLightClient struct{} + +func (m *mockLightClient) VerifyMembership(uint64, []byte, []byte, []byte) error { return nil } +func (m *mockLightClient) VerifyNonMembership(uint64, []byte, []byte) error { return nil } +func (m *mockLightClient) GetTimestamp() types.Timestamp { return types.Timestamp(1) } +func (m *mockLightClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { return types.Timestamp(1), nil } +func (m *mockLightClient) GetLatestHeight() uint64 { return 1 } +func (m *mockLightClient) GetCounterpartyChainID() string { return "mock-chain" } +func (m *mockLightClient) Status() lightclient.Status { return lightclient.Active } + +func (m *mockLightClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { + return types.StateUpdate{Height: 1, ClientStateBytes: header, ConsensusStateBytes: header}, nil +} + +func (m *mockLightClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { + return types.ClientCreationResult{}, nil +} + +func (m *mockLightClient) Misbehaviour(address, []byte, address) ([]byte, error) { + return nil, mockError("mock: misbehaviour unsupported") +} + +type mockError string + +func (e mockError) Error() string { return string(e) } + +// Output: +// [SCENARIO] 1. Bootstrap core+zkgm and open a client/connection (app not yet registered) +// [INFO] app bound at zkgm port: false +// [EXPECTED] no app should be bound at the port yet +// +// [SCENARIO] 2. Register the zkgm app at its port +// [INFO] app bound at zkgm port: true +// [EXPECTED] the zkgm app should now be bound +// +// [SCENARIO] 3. Channel handshake routes OnChannelOpenInit/Ack to the app (Init -> Open) +// [INFO] channel 1 after OpenInit: state=Init +// [INFO] channel 1 after OpenAck: state=Open +// [EXPECTED] channel should advance Init -> Open as the app handles each handshake leg diff --git a/gno.land/r/onbloc/ibc/scenario/union/app/reject_duplicate_app_registration_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/app/reject_duplicate_app_registration_filetest.gno new file mode 100644 index 00000000..9008f774 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/app/reject_duplicate_app_registration_filetest.gno @@ -0,0 +1,55 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/app +package app + +// reject_duplicate_app_registration_filetest is the EXCEPTION-path app scenario. A +// port routes to exactly one IBC app, so registering a second app at a port that is +// already bound is rejected. The zkgm app binds at its proxy port during bootstrap; +// a second RegisterCoreApp for the same port is the terminating panic, matched by +// the // Error: directive. + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap core+zkgm and register the zkgm app at its port") + bootstrap(cur) + ufmt.Printf("[INFO] zkgm app bound at its port: %t\n", core.HasApp([]byte(zkgm.ProxyPkgPath()))) + ufmt.Println("[EXPECTED] the zkgm app should be registered at its proxy port") + println("") + + println("[SCENARIO] 2. Registering a second app at the same port -> rejected") + zkgm.RegisterCoreApp(cross(cur)) +} + +// bootstrap installs the core/zkgm impls and registers the zkgm app once. UpdateImpl +// is admin-gated, so SetRealm(admin) and the cross(cur) calls share this frame. +func bootstrap(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.RegisterCoreApp(cross(cur)) +} + +// Output: +// [SCENARIO] 1. Bootstrap core+zkgm and register the zkgm app at its port +// [INFO] zkgm app bound at its port: true +// [EXPECTED] the zkgm app should be registered at its proxy port +// +// [SCENARIO] 2. Registering a second app at the same port -> rejected + +// Error: +// port gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm already registered diff --git a/gno.land/r/onbloc/ibc/scenario/union/app/route_to_custom_app_by_port_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/app/route_to_custom_app_by_port_filetest.gno new file mode 100644 index 00000000..03d4fed4 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/app/route_to_custom_app_by_port_filetest.gno @@ -0,0 +1,153 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/app +package app + +// route_to_custom_app_by_port_filetest is the BY-TYPE app scenario. Core routes IBC +// callbacks by port to whichever app.IApp implementation is registered there — it is +// app-agnostic. This scenario registers a CUSTOM (non-zkgm) app at the scenario +// realm's own port and drives a channel handshake to it; the custom app records each +// callback it receives, proving core routed the handshake legs to it by port. + +import ( + "strings" + "testing" + + "gno.land/p/nt/ufmt/v0" + "gno.land/p/onbloc/ibc/union/lightclient" + types "gno.land/p/onbloc/ibc/union/types" + + "gno.land/r/onbloc/ibc/union/access" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + + // customPort is the scenario realm's own package path; registering from this + // realm binds the custom app at this port. + customPort = "gno.land/r/onbloc/ibc/scenario/union/app" + customVersion = "custom-app-v1" + mockClientType = types.ClientType("scenario-mock-lc") +) + +// routed records, in order, the callbacks core delivered to the custom app. +var routed []string + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap core and register a CUSTOM app at the scenario realm's port") + connectionId := bootstrap(cur) + ufmt.Printf("[INFO] custom app bound at its port: %t\n", core.HasApp([]byte(customPort))) + ufmt.Println("[EXPECTED] the custom (non-zkgm) app should be bound at its own port") + println("") + + println("[SCENARIO] 2. A channel handshake to that port routes callbacks to the custom app") + openChannel(cur, connectionId) + ufmt.Printf("[INFO] callbacks the custom app received: %s\n", strings.Join(routed, " -> ")) + ufmt.Println("[EXPECTED] core should route OnChannelOpenInit then OnChannelOpenAck to the custom app") +} + +// bootstrap installs the core impl, opens a mock-backed client/connection, and +// registers the custom app at the scenario realm's port. The admin ops run under +// SetRealm(admin); the registration runs under the scenario code realm so the +// derived port is customPort. +func bootstrap(cur realm) types.ConnectionId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + + core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { + return &mockLightClient{}, nil + }) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + // Register the custom app as the scenario code realm so its port is customPort. + testing.SetRealm(testing.NewCodeRealm(customPort)) + core.RegisterApp(cross(cur), &customApp{}) + return connectionId +} + +func openChannel(cur realm, connectionId types.ConnectionId) { + portId := []byte(customPort) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, customVersion, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, customVersion, types.ChannelId(2), nil, 1, "g1relayer")) +} + +// --- custom IBC app: records each routed callback, accepts any channel version --- + +type customApp struct{} + +func (a *customApp) OnChannelOpenInit(_ realm, _ types.ConnectionId, _ types.ChannelId, _ string, _ address) { + routed = append(routed, "OnChannelOpenInit") +} + +func (a *customApp) OnChannelOpenTry(_ realm, _ types.ConnectionId, _ types.ChannelId, _ string, _ string, _ address) { + routed = append(routed, "OnChannelOpenTry") +} + +func (a *customApp) OnChannelOpenAck(_ realm, _ types.ChannelId, _ types.ChannelId, _ string, _ address) { + routed = append(routed, "OnChannelOpenAck") +} + +func (a *customApp) OnChannelOpenConfirm(_ realm, _ types.ChannelId, _ address) { + routed = append(routed, "OnChannelOpenConfirm") +} + +func (a *customApp) OnChannelCloseInit(_ realm, _ types.ChannelId, _ address) {} +func (a *customApp) OnChannelCloseConfirm(_ realm, _ types.ChannelId, _ address) {} + +func (a *customApp) OnRecvPacket(_ realm, _ types.Packet, _ address, _ []byte) types.RecvPacketResult { + return core.NewRecvPacketResult(types.PacketStatusSuccess, nil) +} + +func (a *customApp) OnAcknowledgementPacket(_ realm, _ types.Packet, _ []byte, _ address) {} +func (a *customApp) OnTimeoutPacket(_ realm, _ types.Packet, _ address) {} + +func (a *customApp) OnIntentRecvPacket(_ realm, _ types.Packet, _ address, _ []byte) types.RecvPacketResult { + return core.NewRecvPacketResult(types.PacketStatusSuccess, nil) +} + +// --- permissive mock light client (accepts any proof) --- + +type mockLightClient struct{} + +func (m *mockLightClient) VerifyMembership(uint64, []byte, []byte, []byte) error { return nil } +func (m *mockLightClient) VerifyNonMembership(uint64, []byte, []byte) error { return nil } +func (m *mockLightClient) GetTimestamp() types.Timestamp { return types.Timestamp(1) } +func (m *mockLightClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { return types.Timestamp(1), nil } +func (m *mockLightClient) GetLatestHeight() uint64 { return 1 } +func (m *mockLightClient) GetCounterpartyChainID() string { return "mock-chain" } +func (m *mockLightClient) Status() lightclient.Status { return lightclient.Active } + +func (m *mockLightClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { + return types.StateUpdate{Height: 1, ClientStateBytes: header, ConsensusStateBytes: header}, nil +} + +func (m *mockLightClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { + return types.ClientCreationResult{}, nil +} + +func (m *mockLightClient) Misbehaviour(address, []byte, address) ([]byte, error) { + return nil, mockError("mock: misbehaviour unsupported") +} + +type mockError string + +func (e mockError) Error() string { return string(e) } + +// Output: +// [SCENARIO] 1. Bootstrap core and register a CUSTOM app at the scenario realm's port +// [INFO] custom app bound at its port: true +// [EXPECTED] the custom (non-zkgm) app should be bound at its own port +// +// [SCENARIO] 2. A channel handshake to that port routes callbacks to the custom app +// [INFO] callbacks the custom app received: OnChannelOpenInit -> OnChannelOpenAck +// [EXPECTED] core should route OnChannelOpenInit then OnChannelOpenAck to the custom app diff --git a/gno.land/r/onbloc/ibc/scenario/union/batch/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/batch/gnomod.toml new file mode 100644 index 00000000..afd0bd0e --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/batch/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/batch" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/batch/large_batch_and_nested_rejection_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/batch/large_batch_and_nested_rejection_filetest.gno new file mode 100644 index 00000000..941e183d --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/batch/large_batch_and_nested_rejection_filetest.gno @@ -0,0 +1,197 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/batch +package batch + +// large_batch_and_nested_rejection_filetest is the BY-TYPE batch scenario for the +// current batch limits (re-targeted from the legacy e2e zs89). A flat batch has no +// length cap: an 8-child batch of INITIALIZE orders mints all eight vouchers. A +// nested batch (a batch whose child is itself a batch) is rejected — its receive +// writes a failure acknowledgement and mints nothing new. The mint count is the +// observable: 8 after the flat batch, still 8 after the nested batch. (The legacy +// exact ack-hash equality used e2e ack builders; the unchanged mint count is the +// behavior-level proof the nested batch was rejected.) + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + quoteTokens, instructions := buildChildren(channelId) + + println("[SCENARIO] 2. A flat batch of 8 INITIALIZE children mints all eight (no length cap)") + recvFlatBatch(cur, channelId, instructions, quoteTokens) + println("") + + println("[SCENARIO] 3. A nested batch (batch inside batch) is rejected, minting nothing new") + recvNestedBatch(cur, channelId, quoteTokens) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +// buildChildren derives 8 distinct wrapped tokens and their INITIALIZE instructions +// (one unit each). +func buildChildren(channelId types.ChannelId) (quoteTokens []string, instructions []z.Instruction) { + bases := []string{"zs89-a", "zs89-b", "zs89-c", "zs89-d", "zs89-e", "zs89-f", "zs89-g", "zs89-h"} + quoteTokens = make([]string, len(bases)) + instructions = make([]z.Instruction, len(bases)) + for i, base := range bases { + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: base, Symbol: "ZS89", Decimals: 6}) + quoteTokens[i] = z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte(base), z.MetadataImage(mustDecodeMeta(meta))) + instructions[i] = mustOrderInstruction(z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte(base), + BaseAmount: u256.NewUint(1), + QuoteToken: []byte(quoteTokens[i]), + QuoteAmount: u256.NewUint(1), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + }) + } + return quoteTokens, instructions +} + +func recvFlatBatch(cur realm, channelId types.ChannelId, instructions []z.Instruction, quoteTokens []string) { + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustBatchInstruction(z.Batch{Instructions: instructions})), types.Timestamp(1<<62)) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + ufmt.Printf("[INFO] minted children: %d\n", mintedChildren(quoteTokens)) + ufmt.Printf("[INFO] packet receipt recorded: %t\n", receiptRecorded(packet)) + ufmt.Println("[EXPECTED] all 8 children minted; receipt recorded") +} + +func recvNestedBatch(cur realm, channelId types.ChannelId, quoteTokens []string) { + nested := z.Batch{Instructions: []z.Instruction{mustBatchInstruction(z.Batch{})}} + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustBatchInstruction(nested)), types.Timestamp(1<<62)) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + ufmt.Printf("[INFO] minted children after nested batch: %d\n", mintedChildren(quoteTokens)) + ufmt.Printf("[INFO] packet receipt recorded: %t\n", receiptRecorded(packet)) + ufmt.Println("[EXPECTED] nested batch rejected: mint count unchanged at 8; receipt recorded (failure ack)") +} + +func mintedChildren(quoteTokens []string) int { + n := 0 + for _, qt := range quoteTokens { + if zkgm.VoucherBalanceOf(qt, receiverAddr) == 1 { + n++ + } + } + return n +} + +func receiptRecorded(packet types.Packet) bool { + _, err := core.GetBatchReceipts(core.CommitPacketsHash([]types.Packet{packet})) + return err == nil +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustBatchInstruction(b z.Batch) z.Instruction { + operand, err := z.EncodeBatch(b) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_0, Opcode: z.OP_BATCH, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. A flat batch of 8 INITIALIZE children mints all eight (no length cap) +// [INFO] minted children: 8 +// [INFO] packet receipt recorded: true +// [EXPECTED] all 8 children minted; receipt recorded +// +// [SCENARIO] 3. A nested batch (batch inside batch) is rejected, minting nothing new +// [INFO] minted children after nested batch: 8 +// [INFO] packet receipt recorded: true +// [EXPECTED] nested batch rejected: mint count unchanged at 8; receipt recorded (failure ack) diff --git a/gno.land/r/onbloc/ibc/scenario/union/batch/recv_batch_token_order_and_call_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/batch/recv_batch_token_order_and_call_filetest.gno new file mode 100644 index 00000000..f8105119 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/batch/recv_batch_token_order_and_call_filetest.gno @@ -0,0 +1,177 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/batch +package batch + +// recv_batch_token_order_and_call_filetest is the NORMAL-path batch scenario +// (re-targeted from the legacy e2e z24). A single received OP_BATCH carries two +// children — an INITIALIZE TokenOrder and an OP_CALL to a registered receiver. The +// dispatcher executes both: the TokenOrder mints the wrapped voucher to the +// receiver, and the Call is delivered to the mock receiver realm (its OnZkgm +// handler runs once with the packet's calldata). Both effects are verified, along +// with the recorded receipt. + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" + mockrcv "gno.land/r/onbloc/ibc/testing/mock/receiver" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + receiverPath = "gno.land/r/onbloc/ibc/testing/mock/receiver" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host, open a channel, and reset the mock receiver") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Receive an OP_BATCH of [INITIALIZE TokenOrder, OP_CALL]: both children execute") + recvBatch(cur, channelId, quoteToken, meta) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + + // The mock receiver self-registers in its init; clear any captured state. + mockrcv.Reset(cross(cur)) + return channelId +} + +func recvBatch(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + batch := z.Batch{Instructions: []z.Instruction{ + mustOrderInstruction(z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(100), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + }), + mustCallInstruction(z.Call{ + Sender: []byte("remote-sender"), + ContractAddress: []byte(receiverPath), + ContractCalldata: []byte("post-transfer-action"), + }), + }} + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustBatchInstruction(batch)), types.Timestamp(1<<62)) + + voucherBefore := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + ufmt.Printf("[INFO] TokenOrder child: receiver voucher %d -> %d\n", voucherBefore, zkgm.VoucherBalanceOf(quoteToken, receiverAddr)) + ufmt.Printf("[INFO] Call child: mock receiver OnZkgm calls = %d, calldata = %q\n", mockrcv.Calls(cross(cur)), mockrcv.LastCalldata(cross(cur))) + ufmt.Printf("[INFO] packet receipt recorded: %t\n", receiptRecorded(packet)) + ufmt.Println("[EXPECTED] TokenOrder mints 100 and the Call reaches the receiver exactly once") +} + +func receiptRecorded(packet types.Packet) bool { + _, err := core.GetBatchReceipts(core.CommitPacketsHash([]types.Packet{packet})) + return err == nil +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustCallInstruction(call z.Call) z.Instruction { + operand, err := z.EncodeCall(call) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_0, Opcode: z.OP_CALL, Operand: operand} +} + +func mustBatchInstruction(b z.Batch) z.Instruction { + operand, err := z.EncodeBatch(b) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_0, Opcode: z.OP_BATCH, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host, open a channel, and reset the mock receiver +// +// [SCENARIO] 2. Receive an OP_BATCH of [INITIALIZE TokenOrder, OP_CALL]: both children execute +// [INFO] TokenOrder child: receiver voucher 0 -> 100 +// [INFO] Call child: mock receiver OnZkgm calls = 1, calldata = "post-transfer-action" +// [INFO] packet receipt recorded: true +// [EXPECTED] TokenOrder mints 100 and the Call reaches the receiver exactly once diff --git a/gno.land/r/onbloc/ibc/scenario/union/client/create_and_update_client_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/client/create_and_update_client_filetest.gno new file mode 100644 index 00000000..3d334ab3 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/client/create_and_update_client_filetest.gno @@ -0,0 +1,173 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/client +package client + +// create_and_update_client_filetest is the NORMAL-path client-lifecycle scenario. +// It registers a light-client type, creates a client (id 1, Active), then updates +// it with a header that advances the verified height. The client's status and +// latest height are verified as a before/after diff across each step. + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + "gno.land/p/onbloc/ibc/union/lightclient" + types "gno.land/p/onbloc/ibc/union/types" + + "gno.land/r/onbloc/ibc/union/access" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + + mockClientType = types.ClientType("scenario-mock-lc") + genesisHeight = uint64(1) + updatedHeight = uint64(7) +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap core and register a light-client type") + bootstrap(cur) + println("") + + println("[SCENARIO] 2. Create a client of that type") + clientId := createClient(cur) + println("") + + println("[SCENARIO] 3. Update the client with a header advancing the height") + updateClient(cur, clientId) +} + +// bootstrap installs the core impl and grants the admin the relayer role (client +// lifecycle entrypoints are relayer-gated). SetRealm and the cross(cur) calls share +// this frame so the admin is the authorized caller. +func bootstrap(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + + core.RegisterClient(cross(cur), mockClientType, func(csBytes, _ []byte) (lightclient.Interface, error) { + return &mockClient{height: decodeHeight(csBytes), chainID: "mock-counterparty"}, nil + }) + ufmt.Printf("[INFO] client type registered: %t\n", core.GetRegisteredClientType(mockClientType)) + ufmt.Println("[EXPECTED] the mock client type should be registered") +} + +// createClient creates a client seeded at genesisHeight and reports its identity. +func createClient(cur realm) types.ClientId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mockClientType, encodeHeight(genesisHeight), encodeHeight(genesisHeight))) + clientId := types.ClientId(1) + + reportStatus(clientId, "after create") + ufmt.Println("[EXPECTED] first client should be id 1, status Active, latest height 1") + return clientId +} + +// updateClient submits a header advancing the verified height, then reports the +// height as a diff against the create-time value. +func updateClient(cur realm, clientId types.ClientId) { + before, _ := core.GetLatestHeight(clientId) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateClient(cross(cur), types.NewMsgUpdateClient(clientId, encodeHeight(updatedHeight))) + + after, _ := core.GetLatestHeight(clientId) + ufmt.Printf("[INFO] latest height: %d -> %d\n", before, after) + reportStatus(clientId, "after update") + ufmt.Println("[EXPECTED] latest height should advance 1 -> 7 and the client stay Active") +} + +func reportStatus(clientId types.ClientId, label string) { + status, _ := core.GetStatus(clientId) + height, _ := core.GetLatestHeight(clientId) + ufmt.Printf("[INFO] client %s %s: status=%s height=%d\n", clientId.String(), label, statusLabel(status), height) +} + +// statusLabel maps the uint8 types.Status to a readable name (types.Status has no +// String method). +func statusLabel(s types.Status) string { + switch s { + case types.StatusActive: + return "Active" + case types.StatusExpired: + return "Expired" + case types.StatusFrozen: + return "Frozen" + default: + return "Unknown" + } +} + +// --- height codec (8-byte big-endian) --- + +func encodeHeight(h uint64) []byte { + out := make([]byte, 8) + for i := 0; i < 8; i++ { + out[7-i] = byte(h >> (8 * i)) + } + return out +} + +func decodeHeight(b []byte) uint64 { + if len(b) < 8 { + return 0 + } + var h uint64 + for i := 0; i < 8; i++ { + h = h<<8 | uint64(b[i]) + } + return h +} + +// --- mock light client with a mutable verified height and freeze flag --- + +type mockClient struct { + height uint64 + frozen bool + chainID string +} + +func (m *mockClient) VerifyMembership(uint64, []byte, []byte, []byte) error { return nil } +func (m *mockClient) VerifyNonMembership(uint64, []byte, []byte) error { return nil } +func (m *mockClient) GetTimestamp() types.Timestamp { return types.Timestamp(1) } +func (m *mockClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { return types.Timestamp(1), nil } +func (m *mockClient) GetLatestHeight() uint64 { return m.height } +func (m *mockClient) GetCounterpartyChainID() string { return m.chainID } + +func (m *mockClient) Status() lightclient.Status { + if m.frozen { + return lightclient.Frozen + } + return lightclient.Active +} + +func (m *mockClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { + m.height = decodeHeight(header) + return types.StateUpdate{Height: m.height, ClientStateBytes: header, ConsensusStateBytes: header}, nil +} + +func (m *mockClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { + return types.ClientCreationResult{}, nil +} + +func (m *mockClient) Misbehaviour(address, []byte, address) ([]byte, error) { + m.frozen = true + return encodeHeight(m.height), nil +} + +// Output: +// [SCENARIO] 1. Bootstrap core and register a light-client type +// [INFO] client type registered: true +// [EXPECTED] the mock client type should be registered +// +// [SCENARIO] 2. Create a client of that type +// [INFO] client 1 after create: status=Active height=1 +// [EXPECTED] first client should be id 1, status Active, latest height 1 +// +// [SCENARIO] 3. Update the client with a header advancing the height +// [INFO] latest height: 1 -> 7 +// [INFO] client 1 after update: status=Active height=7 +// [EXPECTED] latest height should advance 1 -> 7 and the client stay Active diff --git a/gno.land/r/onbloc/ibc/scenario/union/client/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/client/gnomod.toml new file mode 100644 index 00000000..dc3b4539 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/client/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/client" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/client/reject_create_unregistered_type_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/client/reject_create_unregistered_type_filetest.gno new file mode 100644 index 00000000..c7112fa2 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/client/reject_create_unregistered_type_filetest.gno @@ -0,0 +1,51 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/client +package client + +// reject_create_unregistered_type_filetest is the EXCEPTION-path client scenario. +// A client type must be registered before a client of that type can be created. +// The admin is relayer-authorized (so the access gate passes), but no client type +// is registered, so CreateClient is rejected once it reaches the registry lookup. +// The rejection is the terminating panic, matched by the // Error: directive. + +import ( + "testing" + + types "gno.land/p/onbloc/ibc/union/types" + + "gno.land/r/onbloc/ibc/union/access" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + + unregisteredType = types.ClientType("never-registered-lc") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap core and authorize the admin as relayer (no client type registered)") + bootstrap(cur) + println("") + + println("[SCENARIO] 2. Creating a client of an unregistered type -> rejected") + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(unregisteredType, nil, nil)) +} + +// bootstrap installs the core impl and grants the admin the relayer role so the +// CreateClient access gate passes and the failure is specifically the missing type. +func bootstrap(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) +} + +// Output: +// [SCENARIO] 1. Bootstrap core and authorize the admin as relayer (no client type registered) +// +// [SCENARIO] 2. Creating a client of an unregistered type -> rejected + +// Error: +// client type not found diff --git a/gno.land/r/onbloc/ibc/scenario/union/client/update_paths_by_kind_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/client/update_paths_by_kind_filetest.gno new file mode 100644 index 00000000..d9b3827a --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/client/update_paths_by_kind_filetest.gno @@ -0,0 +1,170 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/client +package client + +// update_paths_by_kind_filetest is the BY-TYPE client scenario. It contrasts the +// two distinct ways a client's state is advanced: +// - the verified path (UpdateClient), which runs the light client's header +// verification and is only allowed while the client is Active, and +// - the admin override path (ForceUpdateClient), which rebuilds the client from +// submitted bytes, bypassing verification — so it can even recover a frozen +// client back to Active. +// Each step reports the client's status/height so the transitions read as diffs. + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + "gno.land/p/onbloc/ibc/union/lightclient" + types "gno.land/p/onbloc/ibc/union/types" + + "gno.land/r/onbloc/ibc/union/access" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + + mockClientType = types.ClientType("scenario-mock-lc") + genesisHeight = uint64(1) + verifiedHeight = uint64(5) + forcedHeight = uint64(9) +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap, register the type, and create a client") + clientId := bootstrapAndCreate(cur) + report(clientId, "after create") + println("") + + println("[SCENARIO] 2. VERIFIED path: UpdateClient runs header verification (client must be Active)") + verifiedUpdate(cur, clientId) + report(clientId, "after UpdateClient") + println("") + + println("[SCENARIO] 3. Freeze the client via Misbehaviour") + freeze(cur, clientId) + report(clientId, "after Misbehaviour") + println("") + + println("[SCENARIO] 4. ADMIN OVERRIDE path: ForceUpdateClient rebuilds and recovers the frozen client") + forcedUpdate(cur, clientId) + report(clientId, "after ForceUpdateClient") + println("[EXPECTED] verified path advances height while Active; force path rebuilds Active from Frozen") +} + +func bootstrapAndCreate(cur realm) types.ClientId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + core.RegisterClient(cross(cur), mockClientType, func(csBytes, _ []byte) (lightclient.Interface, error) { + return &mockClient{height: decodeHeight(csBytes)}, nil + }) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mockClientType, encodeHeight(genesisHeight), encodeHeight(genesisHeight))) + return types.ClientId(1) +} + +func verifiedUpdate(cur realm, clientId types.ClientId) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateClient(cross(cur), types.NewMsgUpdateClient(clientId, encodeHeight(verifiedHeight))) +} + +func freeze(cur realm, clientId types.ClientId) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.Misbehaviour(cross(cur), types.NewMsgMisbehaviour(clientId, []byte("evidence"), "g1relayer")) +} + +func forcedUpdate(cur realm, clientId types.ClientId) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.ForceUpdateClient(cross(cur), types.NewMsgForceUpdateClient(clientId, encodeHeight(forcedHeight), encodeHeight(forcedHeight))) +} + +func report(clientId types.ClientId, label string) { + status, _ := core.GetStatus(clientId) + height, _ := core.GetLatestHeight(clientId) + ufmt.Printf("[INFO] client %s %s: status=%s height=%d\n", clientId.String(), label, statusLabel(status), height) +} + +func statusLabel(s types.Status) string { + switch s { + case types.StatusActive: + return "Active" + case types.StatusExpired: + return "Expired" + case types.StatusFrozen: + return "Frozen" + default: + return "Unknown" + } +} + +// --- height codec (8-byte big-endian) --- + +func encodeHeight(h uint64) []byte { + out := make([]byte, 8) + for i := 0; i < 8; i++ { + out[7-i] = byte(h >> (8 * i)) + } + return out +} + +func decodeHeight(b []byte) uint64 { + if len(b) < 8 { + return 0 + } + var h uint64 + for i := 0; i < 8; i++ { + h = h<<8 | uint64(b[i]) + } + return h +} + +// --- mock light client with a mutable verified height and freeze flag --- + +type mockClient struct { + height uint64 + frozen bool +} + +func (m *mockClient) VerifyMembership(uint64, []byte, []byte, []byte) error { return nil } +func (m *mockClient) VerifyNonMembership(uint64, []byte, []byte) error { return nil } +func (m *mockClient) GetTimestamp() types.Timestamp { return types.Timestamp(1) } +func (m *mockClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { return types.Timestamp(1), nil } +func (m *mockClient) GetLatestHeight() uint64 { return m.height } +func (m *mockClient) GetCounterpartyChainID() string { return "mock-counterparty" } + +func (m *mockClient) Status() lightclient.Status { + if m.frozen { + return lightclient.Frozen + } + return lightclient.Active +} + +func (m *mockClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { + m.height = decodeHeight(header) + return types.StateUpdate{Height: m.height, ClientStateBytes: header, ConsensusStateBytes: header}, nil +} + +func (m *mockClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { + return types.ClientCreationResult{}, nil +} + +func (m *mockClient) Misbehaviour(address, []byte, address) ([]byte, error) { + m.frozen = true + return encodeHeight(m.height), nil +} + +// Output: +// [SCENARIO] 1. Bootstrap, register the type, and create a client +// [INFO] client 1 after create: status=Active height=1 +// +// [SCENARIO] 2. VERIFIED path: UpdateClient runs header verification (client must be Active) +// [INFO] client 1 after UpdateClient: status=Active height=5 +// +// [SCENARIO] 3. Freeze the client via Misbehaviour +// [INFO] client 1 after Misbehaviour: status=Frozen height=5 +// +// [SCENARIO] 4. ADMIN OVERRIDE path: ForceUpdateClient rebuilds and recovers the frozen client +// [INFO] client 1 after ForceUpdateClient: status=Active height=9 +// [EXPECTED] verified path advances height while Active; force path rebuilds Active from Frozen diff --git a/gno.land/r/onbloc/ibc/scenario/union/decimals/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/decimals/gnomod.toml new file mode 100644 index 00000000..0c6febcb --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/decimals/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/decimals" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/decimals/recv_18dec_no_scaling_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/decimals/recv_18dec_no_scaling_filetest.gno new file mode 100644 index 00000000..d1bbf72f --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/decimals/recv_18dec_no_scaling_filetest.gno @@ -0,0 +1,173 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/decimals +package decimals + +// recv_18dec_no_scaling_filetest is the BY-TYPE scenario for 18-decimal amount +// fidelity (re-targeted from the legacy e2e zs25). An 18-decimal token (1e18 wei) +// is received via an INITIALIZE order and minted 1:1 with no amount scaling; an +// UNESCROW send then burns the exact same 1e18 amount back to zero. The invariant +// is verified by the minted/burned balance, which must equal the wire amount +// exactly. (The legacy `impl.VoucherDecimalsOf` introspection was removed; the +// unscaled balance is the observable that proves no scaling occurred.) + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + holderAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") + + // weiAmount is 1e18 — a full 18-decimal unit. It fits in uint64. + weiAmount = uint64(1000000000000000000) +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Ether Token", Symbol: "ETH", Decimals: 18}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("wei"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Receive an 18-dec INITIALIZE order: minted 1:1 with no scaling") + recvInitialize(cur, channelId, quoteToken, meta) + println("") + + println("[SCENARIO] 3. UNESCROW send burns the exact same 1e18 amount back to zero") + unescrowSend(cur, channelId, quoteToken) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +func recvInitialize(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(holderAddr.String()), + BaseToken: []byte("wei"), + BaseAmount: u256.NewUint(weiAmount), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(weiAmount), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + before := zkgm.VoucherBalanceOf(quoteToken, holderAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + after := zkgm.VoucherBalanceOf(quoteToken, holderAddr) + ufmt.Printf("[INFO] holder voucher balance: %d -> %d\n", before, after) + ufmt.Println("[EXPECTED] minted balance should equal 1000000000000000000 (1e18, unscaled)") +} + +func unescrowSend(cur realm, channelId types.ChannelId, quoteToken string) { + order := z.TokenOrderV2{ + Sender: []byte(holderAddr.String()), + Receiver: []byte("remote-receiver"), + BaseToken: []byte(quoteToken), + BaseAmount: u256.NewUint(weiAmount), + QuoteToken: []byte("wei"), + QuoteAmount: u256.NewUint(weiAmount), + Kind: z.TOKEN_ORDER_KIND_UNESCROW, + } + + before := zkgm.VoucherBalanceOf(quoteToken, holderAddr) + + testing.SetRealm(testing.NewUserRealm(holderAddr)) + _ = zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) + + after := zkgm.VoucherBalanceOf(quoteToken, holderAddr) + ufmt.Printf("[INFO] holder voucher balance: %d -> %d\n", before, after) + ufmt.Println("[EXPECTED] UNESCROW send should burn the full 1e18, leaving 0") +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Receive an 18-dec INITIALIZE order: minted 1:1 with no scaling +// [INFO] holder voucher balance: 0 -> 1000000000000000000 +// [EXPECTED] minted balance should equal 1000000000000000000 (1e18, unscaled) +// +// [SCENARIO] 3. UNESCROW send burns the exact same 1e18 amount back to zero +// [INFO] holder voucher balance: 1000000000000000000 -> 0 +// [EXPECTED] UNESCROW send should burn the full 1e18, leaving 0 diff --git a/gno.land/r/onbloc/ibc/scenario/union/decimals/send_6dec_native_no_scaling_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/decimals/send_6dec_native_no_scaling_filetest.gno new file mode 100644 index 00000000..85bd2abe --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/decimals/send_6dec_native_no_scaling_filetest.gno @@ -0,0 +1,117 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/decimals +package decimals + +// send_6dec_native_no_scaling_filetest is the BY-TYPE scenario for native-coin +// amount fidelity on send (re-targeted from the legacy e2e zs26). A native ESCROW +// send of an odd 6-decimal amount (1234567 ugnot) locks exactly that amount into +// the proxy escrow with no scaling. The legacy `sh.ChannelBalanceStr` channel- +// balance read is re-targeted to the proxy's on-chain native balance, which must +// equal the wire BaseAmount exactly. + +import ( + "chain" + "chain/banker" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + senderAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") + + nativeAmount = int64(1234567) // an odd 6-decimal amount, must not be scaled +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + println("[SCENARIO] 2. Native ESCROW send locks the exact 1234567ugnot with no scaling") + sendNativeEscrow(cur, channelId) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +// sendNativeEscrow locks native ugnot via a user ESCROW send funded by attached +// coins: IssueCoins reproduces the -send deposit landing at the proxy, SetOriginSend +// reproduces the envelope the impl reads to seed the escrow budget. +func sendNativeEscrow(cur realm, channelId types.ChannelId) { + order := z.TokenOrderV2{ + Sender: []byte(senderAddr.String()), + Receiver: []byte("remote-receiver"), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(uint64(nativeAmount)), + QuoteToken: []byte("quote/native"), + QuoteAmount: u256.NewUint(uint64(nativeAmount)), + Kind: z.TOKEN_ORDER_KIND_ESCROW, + } + + proxy := zkgm.ProxyAddress() + testing.IssueCoins(proxy, chain.NewCoins(chain.NewCoin("ugnot", nativeAmount))) + + testing.SetRealm(testing.NewUserRealm(senderAddr)) + testing.SetOriginSend(chain.NewCoins(chain.NewCoin("ugnot", nativeAmount))) + _ = zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) + + bk := banker.NewReadonlyBanker() + ufmt.Printf("[INFO] order base amount: %s\n", order.BaseAmount.ToString()) + ufmt.Printf("[INFO] proxy native escrow balance: %d\n", bk.GetCoins(proxy).AmountOf("ugnot")) + ufmt.Println("[EXPECTED] both should be exactly 1234567 (locked, unscaled)") +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Native ESCROW send locks the exact 1234567ugnot with no scaling +// [INFO] order base amount: 1234567 +// [INFO] proxy native escrow balance: 1234567 +// [EXPECTED] both should be exactly 1234567 (locked, unscaled) diff --git a/gno.land/r/onbloc/ibc/scenario/union/doc.gno b/gno.land/r/onbloc/ibc/scenario/union/doc.gno deleted file mode 100644 index b2b21b23..00000000 --- a/gno.land/r/onbloc/ibc/scenario/union/doc.gno +++ /dev/null @@ -1,3 +0,0 @@ -// Package union holds end-to-end scenario filetests for Union IBC core and -// ucs03-zkgm app interactions. -package union diff --git a/gno.land/r/onbloc/ibc/scenario/union/event_emitters_proxy_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/events/event_emitters_proxy_filetest.gno similarity index 99% rename from gno.land/r/onbloc/ibc/scenario/union/event_emitters_proxy_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/events/event_emitters_proxy_filetest.gno index 45d2e995..7d0a84c2 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/event_emitters_proxy_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/events/event_emitters_proxy_filetest.gno @@ -1,5 +1,5 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/events +package events import ( "testing" diff --git a/gno.land/r/onbloc/ibc/scenario/union/events/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/events/gnomod.toml new file mode 100644 index 00000000..99473caf --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/events/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/events" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/gnomod.toml deleted file mode 100644 index b0c4ac60..00000000 --- a/gno.land/r/onbloc/ibc/scenario/union/gnomod.toml +++ /dev/null @@ -1,2 +0,0 @@ -module = "gno.land/r/onbloc/ibc/scenario/union" -gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/intent/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/intent/gnomod.toml new file mode 100644 index 00000000..ef61ec90 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/intent/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/intent" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/intent/reject_forged_call_via_intent_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/intent/reject_forged_call_via_intent_filetest.gno new file mode 100644 index 00000000..88a69a64 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/intent/reject_forged_call_via_intent_filetest.gno @@ -0,0 +1,112 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/intent +package intent + +// reject_forged_call_via_intent_filetest is the EXCEPTION-path intent scenario +// (re-targeted from the legacy e2e z27). The proofless market-maker fast path +// core.IntentPacketRecv performs no membership verification, so a forged OP_CALL +// delivered through it must fail closed: intent calls are not fillable, the recv +// reverts, and the registered receiver's OnZkgm handler is never reached. The +// revert is the terminating panic, matched by the // Error: directive. + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" + mockrcv "gno.land/r/onbloc/ibc/testing/mock/receiver" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + receiverPath = "gno.land/r/onbloc/ibc/testing/mock/receiver" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap, open a channel, and register the mock receiver") + channelId := bootstrap(cur) + println("") + + println("[SCENARIO] 2. A forged OP_CALL delivered via proofless intent recv must fail closed") + forgedIntentCall(cur, channelId) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + + mockrcv.Reset(cross(cur)) + return channelId +} + +func forgedIntentCall(cur realm, channelId types.ChannelId) { + call := z.Call{ + Sender: []byte("attacker-sender"), + ContractAddress: []byte(receiverPath), + ContractCalldata: []byte("forged-no-proof"), + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustCallInstruction(call)), types.Timestamp(1<<62)) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.IntentPacketRecv(cross(cur), types.NewMsgIntentPacketRecv([]types.Packet{packet}, [][]byte{nil})) + + ufmt.Printf("[INFO] mock receiver OnZkgm calls after forged intent recv: %d\n", mockrcv.Calls(cross(cur))) + ufmt.Println("[EXPECTED] fail closed: the forged call never reaches the receiver handler (calls = 0)") +} + +// --- encoding helpers --- + +func mustCallInstruction(call z.Call) z.Instruction { + operand, err := z.EncodeCall(call) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_0, Opcode: z.OP_CALL, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +// Output: +// [SCENARIO] 1. Bootstrap, open a channel, and register the mock receiver +// +// [SCENARIO] 2. A forged OP_CALL delivered via proofless intent recv must fail closed +// [INFO] mock receiver OnZkgm calls after forged intent recv: 0 +// [EXPECTED] fail closed: the forged call never reaches the receiver handler (calls = 0) diff --git a/gno.land/r/onbloc/ibc/scenario/union/pause/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/pause/gnomod.toml new file mode 100644 index 00000000..5e99ab82 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/pause/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/pause" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/pause/pause_authority_by_caller_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/pause/pause_authority_by_caller_filetest.gno new file mode 100644 index 00000000..d629fc8c --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/pause/pause_authority_by_caller_filetest.gno @@ -0,0 +1,51 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/pause +package pause + +// pause_authority_by_caller_filetest is the BY-TYPE pause scenario. The pause switch +// is a privileged control, gated by the access manager on the "pausable" selector +// (which defaults to AdminRole). It contrasts the two caller types: the admin may +// flip the switch (both pause and unpause succeed), while a non-admin caller is +// rejected. The non-admin attempt is the terminating panic, matched by // Error:. + +import ( + "testing" + + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" +) + +const ( + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // holds AdminRole + nonAdminAddr = address("g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu") // holds no role +) + +func main(cur realm) { + println("[SCENARIO] 1. ADMIN: the admin may pause and unpause the app") + pauseAsAdmin(cur) + println("[EXPECTED] both pause and unpause should succeed for the admin") + println("") + + println("[SCENARIO] 2. NON-ADMIN: a non-admin caller may not flip the pause switch -> rejected") + testing.SetRealm(testing.NewUserRealm(nonAdminAddr)) + zkgm.Pausable(cross(cur), true) +} + +// pauseAsAdmin flips the switch on and back off as the admin. SetRealm(admin) and the +// cross(cur) calls share this frame so the admin is the authorized caller. +func pauseAsAdmin(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + zkgm.Pausable(cross(cur), true) + println("[INFO] admin paused the app") + zkgm.Pausable(cross(cur), false) + println("[INFO] admin unpaused the app") +} + +// Output: +// [SCENARIO] 1. ADMIN: the admin may pause and unpause the app +// [INFO] admin paused the app +// [INFO] admin unpaused the app +// [EXPECTED] both pause and unpause should succeed for the admin +// +// [SCENARIO] 2. NON-ADMIN: a non-admin caller may not flip the pause switch -> rejected + +// Error: +// access manager unauthorized call: g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu is not authorized to call pausable on gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm diff --git a/gno.land/r/onbloc/ibc/scenario/union/pause/pause_then_recv_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/pause/pause_then_recv_filetest.gno new file mode 100644 index 00000000..ef9c0703 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/pause/pause_then_recv_filetest.gno @@ -0,0 +1,188 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/pause +package pause + +// pause_then_recv_filetest is the NORMAL-path pause scenario. The admin pauses the +// zkgm app and then unpauses it — both are admin operations that succeed. Because +// the pause flag has no public getter, its effect is verified positively: after the +// unpause, a packet receive still works and mints the wrapped voucher (a balance +// diff). If the unpause had not taken effect, the receive would abort with "paused". + +import ( + "testing" + + "gno.land/p/nt/ufmt/v0" + "gno.land/p/onbloc/ibc/union/lightclient" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu") + mockClientType = types.ClientType("scenario-mock-lc") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Admin pauses and then unpauses the app") + pauseUnpause(cur) + println("") + + println("[SCENARIO] 3. After unpause, a receive still works and mints the voucher") + receiveInitializeOrder(cur, channelId, quoteToken, meta) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + + core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { + return &mockLightClient{}, nil + }) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +// pauseUnpause flips the global pause switch on and back off. Pausable is admin-gated +// (the admin holds AdminRole), so SetRealm(admin) and the cross(cur) calls share this +// frame. +func pauseUnpause(cur realm) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + zkgm.Pausable(cross(cur), true) + ufmt.Println("[INFO] app paused by admin") + zkgm.Pausable(cross(cur), false) + ufmt.Println("[INFO] app unpaused by admin") + ufmt.Println("[EXPECTED] both pause and unpause should succeed for the admin") +} + +func receiveInitializeOrder(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(100), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + before := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + after := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + ufmt.Printf("[INFO] receiver voucher balance: %d -> %d (delta +%d)\n", before, after, after-before) + ufmt.Println("[EXPECTED] receive should succeed after unpause and mint 100 to the receiver") +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// --- permissive mock light client (accepts any proof) --- + +type mockLightClient struct{} + +func (m *mockLightClient) VerifyMembership(uint64, []byte, []byte, []byte) error { return nil } +func (m *mockLightClient) VerifyNonMembership(uint64, []byte, []byte) error { return nil } +func (m *mockLightClient) GetTimestamp() types.Timestamp { return types.Timestamp(1) } +func (m *mockLightClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { return types.Timestamp(1), nil } +func (m *mockLightClient) GetLatestHeight() uint64 { return 1 } +func (m *mockLightClient) GetCounterpartyChainID() string { return "mock-chain" } +func (m *mockLightClient) Status() lightclient.Status { return lightclient.Active } + +func (m *mockLightClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { + return types.StateUpdate{Height: 1, ClientStateBytes: header, ConsensusStateBytes: header}, nil +} + +func (m *mockLightClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { + return types.ClientCreationResult{}, nil +} + +func (m *mockLightClient) Misbehaviour(address, []byte, address) ([]byte, error) { + return nil, mockError("mock: misbehaviour unsupported") +} + +type mockError string + +func (e mockError) Error() string { return string(e) } + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Admin pauses and then unpauses the app +// [INFO] app paused by admin +// [INFO] app unpaused by admin +// [EXPECTED] both pause and unpause should succeed for the admin +// +// [SCENARIO] 3. After unpause, a receive still works and mints the voucher +// [INFO] receiver voucher balance: 0 -> 100 (delta +100) +// [EXPECTED] receive should succeed after unpause and mint 100 to the receiver diff --git a/gno.land/r/onbloc/ibc/scenario/union/pause/reject_recv_while_paused_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/pause/reject_recv_while_paused_filetest.gno new file mode 100644 index 00000000..68939055 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/pause/reject_recv_while_paused_filetest.gno @@ -0,0 +1,170 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/pause +package pause + +// reject_recv_while_paused_filetest is the EXCEPTION-path pause scenario. The global +// pause flag gates every app callback. While the app is paused, an inbound packet +// receive is rejected before any token is minted. The rejection is the terminating +// panic ("paused"), matched by the // Error: directive. + +import ( + "testing" + + "gno.land/p/onbloc/ibc/union/lightclient" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu") + mockClientType = types.ClientType("scenario-mock-lc") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + println("[SCENARIO] 2. Admin pauses the app") + testing.SetRealm(testing.NewUserRealm(adminAddr)) + zkgm.Pausable(cross(cur), true) + println("[INFO] app paused by admin") + println("") + + println("[SCENARIO] 3. A receive while paused is rejected before minting") + attemptReceive(cur, channelId) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + + core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { + return &mockLightClient{}, nil + }) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +// attemptReceive builds an INITIALIZE order and submits it while the app is paused; +// the zkgm OnRecvPacket gate rejects it with "paused". +func attemptReceive(cur realm, channelId types.ChannelId) { + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + order := z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(100), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// --- permissive mock light client (accepts any proof) --- + +type mockLightClient struct{} + +func (m *mockLightClient) VerifyMembership(uint64, []byte, []byte, []byte) error { return nil } +func (m *mockLightClient) VerifyNonMembership(uint64, []byte, []byte) error { return nil } +func (m *mockLightClient) GetTimestamp() types.Timestamp { return types.Timestamp(1) } +func (m *mockLightClient) GetTimestampAtHeight(uint64) (types.Timestamp, error) { return types.Timestamp(1), nil } +func (m *mockLightClient) GetLatestHeight() uint64 { return 1 } +func (m *mockLightClient) GetCounterpartyChainID() string { return "mock-chain" } +func (m *mockLightClient) Status() lightclient.Status { return lightclient.Active } + +func (m *mockLightClient) VerifyHeader(_ address, header []byte, _ address) (types.StateUpdate, error) { + return types.StateUpdate{Height: 1, ClientStateBytes: header, ConsensusStateBytes: header}, nil +} + +func (m *mockLightClient) VerifyCreation(address, address) (types.ClientCreationResult, error) { + return types.ClientCreationResult{}, nil +} + +func (m *mockLightClient) Misbehaviour(address, []byte, address) ([]byte, error) { + return nil, mockError("mock: misbehaviour unsupported") +} + +type mockError string + +func (e mockError) Error() string { return string(e) } + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Admin pauses the app +// [INFO] app paused by admin +// +// [SCENARIO] 3. A receive while paused is rejected before minting + +// Error: +// paused diff --git a/gno.land/r/onbloc/ibc/scenario/union/ratelimit/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/ratelimit/gnomod.toml new file mode 100644 index 00000000..5a74e507 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/ratelimit/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/ratelimit" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/ratelimit/recv_salt_dedup_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/ratelimit/recv_salt_dedup_filetest.gno new file mode 100644 index 00000000..129b2b0c --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/ratelimit/recv_salt_dedup_filetest.gno @@ -0,0 +1,223 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/ratelimit +package ratelimit + +// recv_salt_dedup_filetest is the BY-TYPE scenario for packet de-duplication via +// salt (re-targeted from the legacy e2e zs87). A packet's commitment is determined +// by its salt: the same sender+salt derives the same salt and yields the same +// packet commitment, while a different salt yields a distinct one. On receive, a +// repeated packet is swallowed by the receipt guard (no double mint), while a +// distinct-salt packet is processed independently. + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + tokenA := newToken(channelId, "ugnot", "Dedup Token", "DDP") + tokenB := newToken(channelId, "uother", "Other Dedup Token", "DDP2") + + println("[SCENARIO] 2. Salt derivation and packet commitment are deterministic") + saltA, saltB := saltDeterminism(channelId, tokenA, tokenB) + println("") + + println("[SCENARIO] 3. A repeated packet (same salt) is swallowed by the receipt guard") + dedupSameSalt(cur, channelId, tokenA, saltA) + println("") + + println("[SCENARIO] 4. A different-salt packet is a distinct packet, processed independently") + distinctSalt(cur, channelId, tokenB, saltB) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +// token bundles a base denom with its metadata and the derived wrapped voucher. +type token struct { + base string + meta []byte + quoteToken string +} + +func newToken(channelId types.ChannelId, base, name, symbol string) token { + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: name, Symbol: symbol, Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte(base), z.MetadataImage(mustDecodeMeta(meta))) + return token{base: base, meta: meta, quoteToken: quoteToken} +} + +func (t token) order() z.TokenOrderV2 { + return z.TokenOrderV2{ + Sender: []byte("same-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte(t.base), + BaseAmount: u256.NewUint(10), + QuoteToken: []byte(t.quoteToken), + QuoteAmount: u256.NewUint(10), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: t.meta, + } +} + +// saltDeterminism asserts salt derivation determinism and packet-commitment +// determinism, returning the two derived salts used by the recv scenarios. +func saltDeterminism(channelId types.ChannelId, tokenA, tokenB token) (saltA, saltB [32]byte) { + var rawA, rawB [32]byte + rawA[31] = 1 + rawB[31] = 2 + + sender := tokenA.order().Sender + saltA = z.DeriveSenderSalt(sender, rawA) + saltA2 := z.DeriveSenderSalt(sender, rawA) + saltB = z.DeriveSenderSalt(sender, rawB) + ufmt.Printf("[INFO] same sender+salt derives equal salt: %t\n", saltA == saltA2) + ufmt.Printf("[INFO] different salt derives distinct salt: %t\n", saltA != saltB) + + packetA := saltedPacket(channelId, saltA, tokenA.order()) + packetA2 := saltedPacket(channelId, saltA, tokenA.order()) + packetB := saltedPacket(channelId, saltB, tokenB.order()) + ufmt.Printf("[INFO] same salt yields equal packet commitment: %t\n", commit(packetA) == commit(packetA2)) + ufmt.Printf("[INFO] different salt yields distinct packet commitment: %t\n", commit(packetA) != commit(packetB)) + ufmt.Println("[EXPECTED] both derivation and commitment should be deterministic in the salt") + return saltA, saltB +} + +func dedupSameSalt(cur realm, channelId types.ChannelId, t token, salt [32]byte) { + packet := saltedPacket(channelId, salt, t.order()) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + first := zkgm.VoucherBalanceOf(t.quoteToken, receiverAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + second := zkgm.VoucherBalanceOf(t.quoteToken, receiverAddr) + + ufmt.Printf("[INFO] receiver balance after first recv: %d (receipt: %t)\n", first, receiptRecorded(packet)) + ufmt.Printf("[INFO] receiver balance after duplicate recv: %d\n", second) + ufmt.Println("[EXPECTED] first recv mints 10; the duplicate is swallowed (balance stays 10)") +} + +func distinctSalt(cur realm, channelId types.ChannelId, t token, salt [32]byte) { + packet := saltedPacket(channelId, salt, t.order()) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + ufmt.Printf("[INFO] distinct-salt packet receipt recorded: %t\n", receiptRecorded(packet)) + ufmt.Printf("[INFO] receiver balance of the other token: %d\n", zkgm.VoucherBalanceOf(t.quoteToken, receiverAddr)) + ufmt.Println("[EXPECTED] the different-salt packet mints its own token (10), independently") +} + +func receiptRecorded(packet types.Packet) bool { + _, err := core.GetBatchReceipts(core.CommitPacketsHash([]types.Packet{packet})) + return err == nil +} + +// --- encoding helpers --- + +func saltedPacket(channelId types.ChannelId, salt [32]byte, order z.TokenOrderV2) types.Packet { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Salt: salt, Path: u256.Zero(), Instruction: mustOrderInstruction(order)}) + if err != nil { + panic(err) + } + return core.NewPacket(types.ChannelId(2), channelId, data, types.Timestamp(1<<62)) +} + +func commit(packet types.Packet) types.H256 { + return types.MustCommit(types.CommitPacket(packet)) +} + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Salt derivation and packet commitment are deterministic +// [INFO] same sender+salt derives equal salt: true +// [INFO] different salt derives distinct salt: true +// [INFO] same salt yields equal packet commitment: true +// [INFO] different salt yields distinct packet commitment: true +// [EXPECTED] both derivation and commitment should be deterministic in the salt +// +// [SCENARIO] 3. A repeated packet (same salt) is swallowed by the receipt guard +// [INFO] receiver balance after first recv: 10 (receipt: true) +// [INFO] receiver balance after duplicate recv: 10 +// [EXPECTED] first recv mints 10; the duplicate is swallowed (balance stays 10) +// +// [SCENARIO] 4. A different-salt packet is a distinct packet, processed independently +// [INFO] distinct-salt packet receipt recorded: true +// [INFO] receiver balance of the other token: 10 +// [EXPECTED] the different-salt packet mints its own token (10), independently diff --git a/gno.land/r/onbloc/ibc/scenario/union/receive/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/receive/gnomod.toml new file mode 100644 index 00000000..cc63758d --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/receive/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/receive" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_receive_by_statelens_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_statelens_filetest.gno similarity index 83% rename from gno.land/r/onbloc/ibc/scenario/union/token_receive_by_statelens_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_statelens_filetest.gno index 6b912ab7..108f645a 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_receive_by_statelens_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_statelens_filetest.gno @@ -1,7 +1,7 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/receive +package receive -// token_receive_by_statelens_filetest receives a ucs03-zkgm token packet proven by +// mint_wrapped_voucher_by_statelens_filetest receives a ucs03-zkgm token packet proven by // the real state-lens/ics23-mpt light client. It builds a single-leaf EVM-MPT // storage proof inline (no exported builder exists), seeds the client's consensus // storage root with it, Force-opens the handshake, and asserts the host mints the @@ -39,21 +39,30 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: install impls, build the proof, open a state-lens channel --- - ufmt.Println("[SCENARIO] 1. Open a channel backed by the real state-lens/ics23-mpt light client") - testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.UpdateImpl(cross(cur), coreImplPath) - zkgm.UpdateImpl(cross(cur), zkgmImplPath) - zkgm.SetRateLimitDisabled(cross(cur), true) - zkgm.RegisterCoreApp(cross(cur)) + fx := buildRecvFixture() - // The relayer-gated host entrypoints (register/create client, handshake, - // packet recv) require RELAYER. Grant it to the admin so this single-actor - // scenario can drive the full flow. - access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + println("[SCENARIO] 1. Open a channel backed by the real state-lens/ics23-mpt light client") + openStateLensChannel(cur, fx.storageRoot, fx.sourceChannel) + println("") - // The first channel opened is ChannelId(1); the wrapped denom and the packet - // are deterministic, so the packet (and its commitment) can be built up front. + println("[SCENARIO] 2. Receive INITIALIZE order proven by the state-lens MPT proof (mint 100)") + receiveProvenOrder(cur, fx.packet, fx.packetProof, fx.quoteToken) +} + +// recvFixture holds the deterministic packet, its proof, and the storage root the +// scenario builds up front and threads through its steps. +type recvFixture struct { + sourceChannel types.ChannelId + storageRoot []byte + packet types.Packet + packetProof []byte + quoteToken string +} + +// buildRecvFixture builds the deterministic recv packet and the single-leaf EVM-MPT +// proof + storage root that commits it. The first channel opened is ChannelId(1), +// so the wrapped denom and the packet are known up front. +func buildRecvFixture() recvFixture { channelId := types.ChannelId(1) sourceChannel := types.ChannelId(2) meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) @@ -69,11 +78,32 @@ func main(cur realm) { Metadata: meta, } packet := core.NewPacket(sourceChannel, channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) - - // Build the EVM-MPT storage proof for this packet's commitment and the storage - // root that commits it; the client's consensus state is seeded with that root. storageRoot, packetProof := buildPacketMembershipProof(packet) + return recvFixture{ + sourceChannel: sourceChannel, + storageRoot: storageRoot, + packet: packet, + packetProof: packetProof, + quoteToken: quoteToken, + } +} + +// openStateLensChannel installs the impls, registers the mock L1 and the real +// state-lens client (seeding its consensus with storageRoot), and Force-opens the +// connection/channel. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func openStateLensChannel(cur realm, storageRoot []byte, sourceChannel types.ChannelId) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + clientState := &ics23mpt.ClientState{ L2ChainID: "l2-chain", L1ClientID: 1, @@ -133,10 +163,12 @@ func main(cur realm) { ufmt.Printf("[INFO] channel opened (source=%s destination=%s)\n", sourceChannel.String(), opened.String()) ufmt.Println("[EXPECTED] client type should be state-lens/ics23/mpt (real, not mock)") ufmt.Println("[EXPECTED] destination channel should be 1") +} - // --- SCENARIO 2: receive the packet proven by the state-lens MPT proof --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. Receive INITIALIZE order proven by the state-lens MPT proof (mint 100)") +// receiveProvenOrder receives the packet proven by the inline state-lens MPT proof +// and asserts the receipt is recorded and the wrapped voucher is minted. +func receiveProvenOrder(cur realm, packet types.Packet, packetProof []byte, quoteToken string) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, packetProof, statelensProofHeight)) _, receiptErr := core.GetBatchReceipts(core.CommitPacketsHash([]types.Packet{packet})) diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_receive_by_statelens_real_cometbls_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_statelens_real_cometbls_filetest.gno similarity index 77% rename from gno.land/r/onbloc/ibc/scenario/union/token_receive_by_statelens_real_cometbls_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_statelens_real_cometbls_filetest.gno index 2a18a780..69bb11f8 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_receive_by_statelens_real_cometbls_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_statelens_real_cometbls_filetest.gno @@ -1,11 +1,11 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/receive +package receive -// token_receive_by_statelens_real_cometbls_filetest receives a ucs03-zkgm token +// mint_wrapped_voucher_by_statelens_real_cometbls_filetest receives a ucs03-zkgm token // packet proven by the real state-lens/ics23-mpt light client whose L1 is a REAL // cometbls light client (not a mock). // -// Unlike token_receive_by_statelens_filetest — which seeds the L2 consensus at +// Unlike mint_wrapped_voucher_by_statelens_filetest — which seeds the L2 consensus at // client creation and stubs the L1 with a mockL1Client — this scenario adds the // L2 consensus via UpdateClient. That drives the state-lens VerifyHeader path, // which asks the L1 cometbls client to prove the L2 consensus state is committed @@ -58,18 +58,38 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: install impls, build the L1 + L2 proofs, open the channel --- - ufmt.Println("[SCENARIO] 1. Open a state-lens channel whose L1 is a REAL cometbls client") - testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.UpdateImpl(cross(cur), coreImplPath) - zkgm.UpdateImpl(cross(cur), zkgmImplPath) - zkgm.SetRateLimitDisabled(cross(cur), true) - zkgm.RegisterCoreApp(cross(cur)) + fx := buildRecvFixture() - access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + println("[SCENARIO] 1. Open a state-lens channel whose L1 is a REAL cometbls client") + clientId := openCometblsStateLensChannel(cur, fx.l1Contract, fx.l1Root, fx.sourceChannel) + println("") + + println("[SCENARIO] 2. UpdateClient: add the L2 consensus, proven by the real cometbls L1") + updateL2Consensus(cur, clientId, fx.l1Proof, fx.l2Consensus) + println("") - // The first channel opened is ChannelId(1); the wrapped denom and the packet - // are deterministic, so the packet (and its commitment) can be built up front. + println("[SCENARIO] 3. Receive INITIALIZE order proven by the state-lens MPT proof (mint 100)") + receiveProvenOrder(cur, fx.packet, fx.packetProof, fx.quoteToken) +} + +// recvFixture holds the deterministic packet, proofs, and consensus blobs the +// scenario builds up front and threads through its steps. +type recvFixture struct { + sourceChannel types.ChannelId + l1Contract types.H256 + l1Root []byte + l1Proof []byte + l2Consensus []byte + packet types.Packet + packetProof []byte + quoteToken string +} + +// buildRecvFixture builds the deterministic recv packet, its inline EVM-MPT proof, +// and the L1 membership proof + cometbls root committing the L2 consensus. The +// first channel opened is ChannelId(1) and a zero L1 contract address is used for +// the proof and the seeded client (they match), so everything is known up front. +func buildRecvFixture() recvFixture { channelId := types.ChannelId(1) sourceChannel := types.ChannelId(2) meta := tokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) @@ -86,20 +106,41 @@ func main(cur realm) { } packet := core.NewPacket(sourceChannel, channelId, packetData(orderInstruction(order)), types.Timestamp(1<<62)) - // The L2 storage root that commits the recv packet, and the inline EVM-MPT - // proof against it. + // storageRoot commits the recv packet; l2Consensus stores it at the client + // offsets (state_root@0, storage_root@32, timestamp@64). storageRoot, packetProof := buildPacketMembershipProof(packet) - - // The L2 consensus blob the state-lens client will store at l2ProofHeight: its - // storage root commits the packet (offsets: state_root@0, storage_root@32, - // timestamp@64). l2Consensus := makeConsensusBytes(1, make([]byte, 32), storageRoot) - // Build the L1 membership proof + the cometbls root committing it. A zero L1 - // contract address is used for the proof and the seeded client (they match). var l1Contract types.H256 l1Proof, l1Root := scenariocometbls.ProveConsensus(l1Contract, types.ClientId(l2ClientID), l2ProofHeight, l2Consensus) + return recvFixture{ + sourceChannel: sourceChannel, + l1Contract: l1Contract, + l1Root: l1Root, + l1Proof: l1Proof, + l2Consensus: l2Consensus, + packet: packet, + packetProof: packetProof, + quoteToken: quoteToken, + } +} + +// openCometblsStateLensChannel creates the real cometbls L1 client (seeded with +// l1Root), creates the state-lens L2 client with a genesis-only consensus, and +// Force-opens the connection/channel. It returns the state-lens client id. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func openCometblsStateLensChannel(cur realm, l1Contract types.H256, l1Root []byte, sourceChannel types.ChannelId) types.ClientId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + // Create the real cometbls L1 client (id 1) seeded with that root. The // register/create calls are made here (as the relayer-authorized admin), // not inside the helper realm, so the access check sees the right caller. @@ -140,9 +181,13 @@ func main(cur realm) { core.ForceChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(opened, zkgm.Version, sourceChannel, nil, 0, "g1relayer")) ufmt.Printf("[INFO] state-lens channel opened (source=%s destination=%s)\n", sourceChannel.String(), opened.String()) - // --- SCENARIO 2: add the L2 consensus via UpdateClient, proven by the L1 --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. UpdateClient: add the L2 consensus, proven by the real cometbls L1") + return clientId +} + +// updateL2Consensus adds the L2 consensus at l2ProofHeight via UpdateClient, which +// drives VerifyHeader -> the real cometbls L1's VerifyMembership on l1Proof. +func updateL2Consensus(cur realm, clientId types.ClientId, l1Proof, l2Consensus []byte) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) header := ics23mpt.Header{ L1Height: l1Height, L2Height: l2ProofHeight, @@ -153,10 +198,12 @@ func main(cur realm) { latest, _ := core.GetLatestHeight(clientId) ufmt.Printf("[INFO] state-lens latest height after L1-proven update: %d\n", latest) ufmt.Println("[EXPECTED] state-lens latest height should be 100 (L2 consensus added via the real L1)") +} - // --- SCENARIO 3: receive the packet proven by the freshly-added consensus --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 3. Receive INITIALIZE order proven by the state-lens MPT proof (mint 100)") +// receiveProvenOrder receives the packet proven by the freshly-added consensus and +// asserts the receipt is recorded and the wrapped voucher is minted. +func receiveProvenOrder(cur realm, packet types.Packet, packetProof []byte, quoteToken string) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, packetProof, l2ProofHeight)) _, receiptErr := core.GetBatchReceipts(core.CommitPacketsHash([]types.Packet{packet})) @@ -183,7 +230,7 @@ func newStateLensClient(csBytes, consBytes []byte) (lightclient.Interface, error // buildPacketMembershipProof returns (storageRoot, encodedProof) for a // single-leaf EVM-MPT proving the packet's BatchPackets commitment path stores -// COMMITMENT_MAGIC. Mirrors token_receive_by_statelens_filetest. +// COMMITMENT_MAGIC. Mirrors mint_wrapped_voucher_by_statelens_filetest. func buildPacketMembershipProof(packet types.Packet) ([]byte, []byte) { batchHash := core.CommitPacketsHash([]types.Packet{packet}) path := types.BatchPacketsPath(batchHash) diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_receive_by_ucs03_zkgm_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_ucs03_zkgm_filetest.gno similarity index 80% rename from gno.land/r/onbloc/ibc/scenario/union/token_receive_by_ucs03_zkgm_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_ucs03_zkgm_filetest.gno index 66988810..72d17215 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_receive_by_ucs03_zkgm_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/receive/mint_wrapped_voucher_by_ucs03_zkgm_filetest.gno @@ -1,7 +1,7 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/receive +package receive -// token_receive_by_ucs03_zkgm_filetest receives ucs03-zkgm token packets through the +// mint_wrapped_voucher_by_ucs03_zkgm_filetest receives ucs03-zkgm token packets through the // upgradeable union IBC host (permissive mock light client) and asserts a wrapped // voucher is minted to the local receiver on each received packet: an INITIALIZE // order deploys and mints the wrapped token, a following ESCROW order mints more of @@ -35,17 +35,35 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: bootstrap (admin) — kept inline so each core call is a - // direct origin call: runtime.AssertOriginCall requires <= 2 call frames. --- - ufmt.Println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + channelId := bootstrap(cur) + println("") + + // The wrapped denom is deterministic for (path=0, channel, base=ugnot, image), + // so it is derived once here and reused by both received orders below. + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Receive INITIALIZE order: deploy wrapped token and mint 100 to receiver A") + receiveInitializeOrder(cur, channelId, quoteToken, meta) + println("") + + println("[SCENARIO] 3. Receive ESCROW order: mint 50 of the same wrapped token to receiver B") + receiveEscrowOrder(cur, channelId, quoteToken) +} + +// bootstrap installs the core/zkgm impls, grants the admin the relayer role, and +// opens a client/connection/channel backed by the permissive mock light client. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func bootstrap(cur realm) types.ChannelId { testing.SetRealm(testing.NewUserRealm(adminAddr)) core.UpdateImpl(cross(cur), coreImplPath) zkgm.UpdateImpl(cross(cur), zkgmImplPath) zkgm.SetRateLimitDisabled(cross(cur), true) zkgm.RegisterCoreApp(cross(cur)) - - // The relayer-gated host entrypoints require RELAYER. Grant it to the admin so - // this single-actor scenario can drive the full flow. access.GrantRole(cross(cur), access.RelayerRole, adminAddr) core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { @@ -62,19 +80,19 @@ func main(cur realm) { core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) channelId := types.ChannelId(1) core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + ufmt.Printf("[INFO] handshake opened: client=%s connection=%s channel=%s\n", clientId.String(), connectionId.String(), channelId.String()) ufmt.Println("[EXPECTED] client should be 1") ufmt.Println("[EXPECTED] connection should be 1") ufmt.Println("[EXPECTED] channel should be 1") - // The wrapped denom is deterministic for (path=0, channel, base=ugnot, image). - meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + return channelId +} - // --- SCENARIO 2: receive an INITIALIZE order, minting to receiver A --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. Receive INITIALIZE order: deploy wrapped token and mint 100 to receiver A") - initOrder := z.TokenOrderV2{ +// receiveInitializeOrder receives an INITIALIZE TokenOrder that deploys the wrapped +// voucher and mints its full amount to receiver A. +func receiveInitializeOrder(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ Sender: []byte("remote-sender"), Receiver: []byte(receiverAAddr.String()), BaseToken: []byte("ugnot"), @@ -84,21 +102,22 @@ func main(cur realm) { Kind: z.TOKEN_ORDER_KIND_INITIALIZE, Metadata: meta, } - initPacket := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(initOrder)), types.Timestamp(1<<62)) + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{initPacket}, [][]byte{nil}, nil, 1)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) ufmt.Printf("[INFO] minted token (wrapped voucher): %s\n", quoteToken) ufmt.Println("[INFO] minted token wraps base token: ugnot") ufmt.Printf("[INFO] receiver A balance: %d\n", zkgm.VoucherBalanceOf(quoteToken, receiverAAddr)) ufmt.Println("[EXPECTED] minted token should be the ibc/ wrapped voucher of base ugnot") ufmt.Println("[EXPECTED] receiver A balance should be 100 (full INITIALIZE amount minted)") +} - // --- SCENARIO 3: receive an ESCROW order for the same asset, minting to receiver B --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 3. Receive ESCROW order: mint 50 of the same wrapped token to receiver B") - escrowOrder := z.TokenOrderV2{ +// receiveEscrowOrder receives an ESCROW TokenOrder for the same asset and mints to +// receiver B, leaving receiver A's balance untouched. +func receiveEscrowOrder(cur realm, channelId types.ChannelId, quoteToken string) { + order := z.TokenOrderV2{ Sender: []byte("remote-sender"), Receiver: []byte(receiverBAddr.String()), BaseToken: []byte("ugnot"), @@ -107,10 +126,10 @@ func main(cur realm) { QuoteAmount: u256.NewUint(50), Kind: z.TOKEN_ORDER_KIND_ESCROW, } - escrowPacket := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(escrowOrder)), types.Timestamp(1<<62)) + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{escrowPacket}, [][]byte{nil}, nil, 1)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) ufmt.Printf("[INFO] minted token (same wrapped voucher): %s\n", quoteToken) ufmt.Printf("[INFO] receiver B balance: %d\n", zkgm.VoucherBalanceOf(quoteToken, receiverBAddr)) diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_receive_native_by_ucs03_zkgm_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/receive/release_native_coin_by_ucs03_zkgm_filetest.gno similarity index 79% rename from gno.land/r/onbloc/ibc/scenario/union/token_receive_native_by_ucs03_zkgm_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/receive/release_native_coin_by_ucs03_zkgm_filetest.gno index 79cc0394..ce5e2ec0 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_receive_native_by_ucs03_zkgm_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/receive/release_native_coin_by_ucs03_zkgm_filetest.gno @@ -1,7 +1,7 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/receive +package receive -// token_receive_native_by_ucs03_zkgm_filetest exercises the native-coin release +// release_native_coin_by_ucs03_zkgm_filetest exercises the native-coin release // path on receive. It first locks native ugnot in the proxy escrow (a user send // funded via the attached-coin OriginSend envelope), then receives an UNESCROW // packet whose base covers the quote. The protocol-fill unescrow decreases the @@ -20,11 +20,11 @@ import ( u256 "gno.land/p/gnoswap/uint256" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" // install zkgm v1 impl (init registers the constructor) core "gno.land/r/onbloc/ibc/union/core" _ "gno.land/r/onbloc/ibc/union/core/v1" - _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" // install zkgm v1 impl (init registers the constructor) ) const ( @@ -42,15 +42,30 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: bootstrap (admin) — kept inline so each core call is a - // direct origin call: runtime.AssertOriginCall requires <= 2 call frames. --- - ufmt.Println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + channelId := bootstrap(cur) + println("") + + println("[SCENARIO] 2. Lock 40ugnot into proxy escrow (native ESCROW send funded by attached coins)") + lockNativeEscrow(cur, channelId) + println("") + + println("[SCENARIO] 3. Receive UNESCROW order: release 40ugnot from escrow back to the user") + receiveUnescrowOrder(cur, channelId) +} + +// bootstrap installs the core/zkgm impls, grants the admin the relayer role, and +// opens a client/connection/channel backed by the permissive mock light client. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func bootstrap(cur realm) types.ChannelId { testing.SetRealm(testing.NewUserRealm(adminAddr)) core.UpdateImpl(cross(cur), coreImplPath) zkgm.UpdateImpl(cross(cur), zkgmImplPath) zkgm.SetRateLimitDisabled(cross(cur), true) zkgm.RegisterCoreApp(cross(cur)) - access.GrantRole(cross(cur), access.RelayerRole, adminAddr) core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { @@ -67,18 +82,20 @@ func main(cur realm) { core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) channelId := types.ChannelId(1) core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + ufmt.Printf("[INFO] handshake opened: client=%s connection=%s channel=%s\n", clientId.String(), connectionId.String(), channelId.String()) ufmt.Println("[EXPECTED] client should be 1") ufmt.Println("[EXPECTED] connection should be 1") ufmt.Println("[EXPECTED] channel should be 1") - bk := banker.NewReadonlyBanker() - proxy := zkgm.ProxyAddress() + return channelId +} - // --- SCENARIO 2: lock native ugnot into the proxy escrow via a user send --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. Lock 40ugnot into proxy escrow (native ESCROW send funded by attached coins)") - lockOrder := z.TokenOrderV2{ +// lockNativeEscrow locks 40 native ugnot into the proxy escrow via a user ESCROW +// send. IssueCoins reproduces the -send deposit landing at the proxy; SetOriginSend +// reproduces the envelope the impl reads to seed the escrow budget. +func lockNativeEscrow(cur realm, channelId types.ChannelId) { + order := z.TokenOrderV2{ Sender: []byte(userAddr.String()), Receiver: []byte("remote-receiver"), BaseToken: []byte("ugnot"), @@ -87,22 +104,24 @@ func main(cur realm) { QuoteAmount: u256.NewUint(40), Kind: z.TOKEN_ORDER_KIND_ESCROW, } - // IssueCoins reproduces the -send deposit landing at the proxy; SetOriginSend - // reproduces the envelope the impl reads to seed the escrow budget. + + proxy := zkgm.ProxyAddress() testing.IssueCoins(proxy, chain.NewCoins(chain.NewCoin("ugnot", 40))) testing.SetRealm(testing.NewUserRealm(userAddr)) testing.SetOriginSend(chain.NewCoins(chain.NewCoin("ugnot", 40))) - _ = zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(lockOrder)) + _ = zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) + bk := banker.NewReadonlyBanker() ufmt.Printf("[INFO] proxy native escrow balance: %d\n", bk.GetCoins(proxy).AmountOf("ugnot")) ufmt.Printf("[INFO] user native balance: %d\n", bk.GetCoins(userAddr).AmountOf("ugnot")) ufmt.Println("[EXPECTED] proxy native escrow balance should be 40 (locked)") ufmt.Println("[EXPECTED] user native balance should be 0 (still escrowed)") +} - // --- SCENARIO 3: receive an UNESCROW packet that releases the native back --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 3. Receive UNESCROW order: release 40ugnot from escrow back to the user") - unescrowOrder := z.TokenOrderV2{ +// receiveUnescrowOrder receives an UNESCROW order that releases the escrowed native +// ugnot from the proxy back to the user via the banker. +func receiveUnescrowOrder(cur realm, channelId types.ChannelId) { + order := z.TokenOrderV2{ Sender: []byte("remote-sender"), Receiver: []byte(userAddr.String()), BaseToken: []byte(quoteWrapped), @@ -111,11 +130,13 @@ func main(cur realm) { QuoteAmount: u256.NewUint(40), Kind: z.TOKEN_ORDER_KIND_UNESCROW, } - unescrowPacket := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(unescrowOrder)), types.Timestamp(1<<62)) + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{unescrowPacket}, [][]byte{nil}, nil, 1)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + bk := banker.NewReadonlyBanker() + proxy := zkgm.ProxyAddress() ufmt.Printf("[INFO] proxy native escrow balance: %d\n", bk.GetCoins(proxy).AmountOf("ugnot")) ufmt.Printf("[INFO] user native balance: %d\n", bk.GetCoins(userAddr).AmountOf("ugnot")) ufmt.Println("[EXPECTED] proxy native escrow balance should be 0 (released)") diff --git a/gno.land/r/onbloc/ibc/scenario/union/send/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/send/gnomod.toml new file mode 100644 index 00000000..9d5e7c87 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/send/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/send" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_send_native_by_ucs03_zkgm_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/send/lock_native_coin_by_ucs03_zkgm_filetest.gno similarity index 78% rename from gno.land/r/onbloc/ibc/scenario/union/token_send_native_by_ucs03_zkgm_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/send/lock_native_coin_by_ucs03_zkgm_filetest.gno index 08581964..5f3199ff 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_send_native_by_ucs03_zkgm_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/send/lock_native_coin_by_ucs03_zkgm_filetest.gno @@ -1,7 +1,7 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/send +package send -// token_send_native_by_ucs03_zkgm_filetest walks a native-coin ucs03-zkgm token +// lock_native_coin_by_ucs03_zkgm_filetest walks a native-coin ucs03-zkgm token // send through the upgradeable union IBC host (permissive mock light client). The // user attaches native ugnot with the call; the impl reads that send envelope via // OriginSend to seed the escrow budget, locks it in the proxy, and the protocol- @@ -20,11 +20,11 @@ import ( u256 "gno.land/p/gnoswap/uint256" - zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" // install zkgm v1 impl (init registers the constructor) core "gno.land/r/onbloc/ibc/union/core" _ "gno.land/r/onbloc/ibc/union/core/v1" - _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" // install zkgm v1 impl (init registers the constructor) ) const ( @@ -37,15 +37,30 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: bootstrap (admin) — kept inline so each core call is a - // direct origin call: runtime.AssertOriginCall requires <= 2 call frames. --- - ufmt.Println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + channelId := bootstrap(cur) + println("") + + println("[SCENARIO] 2. Send native ESCROW order locking 40ugnot (funded via attached send coins)") + sendPacket := sendNativeEscrowOrder(cur, channelId) + println("") + + println("[SCENARIO] 3. Acknowledge with protocol-fill success (no-op for escrow)") + acknowledgeNativeEscrow(cur, sendPacket) +} + +// bootstrap installs the core/zkgm impls, grants the admin the relayer role, and +// opens a client/connection/channel backed by the permissive mock light client. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func bootstrap(cur realm) types.ChannelId { testing.SetRealm(testing.NewUserRealm(adminAddr)) core.UpdateImpl(cross(cur), coreImplPath) zkgm.UpdateImpl(cross(cur), zkgmImplPath) zkgm.SetRateLimitDisabled(cross(cur), true) zkgm.RegisterCoreApp(cross(cur)) - access.GrantRole(cross(cur), access.RelayerRole, adminAddr) core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { @@ -62,15 +77,22 @@ func main(cur realm) { core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) channelId := types.ChannelId(1) core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + ufmt.Printf("[INFO] handshake opened: client=%s connection=%s channel=%s\n", clientId.String(), connectionId.String(), channelId.String()) ufmt.Println("[EXPECTED] client should be 1") ufmt.Println("[EXPECTED] connection should be 1") ufmt.Println("[EXPECTED] channel should be 1") - // --- SCENARIO 2: send a native ESCROW order, funded by attached coins --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. Send native ESCROW order locking 40ugnot (funded via attached send coins)") - escrowOrder := z.TokenOrderV2{ + return channelId +} + +// sendNativeEscrowOrder sends a native ESCROW order funded by attached coins. In +// production the user attaches `-send 40ugnot`, which credits the proxy (the escrow +// account) and shows up in the OriginSend envelope. IssueCoins reproduces the +// deposit; SetOriginSend reproduces the envelope the impl reads to seed its escrow +// budget. It returns the produced packet for later acknowledgement. +func sendNativeEscrowOrder(cur realm, channelId types.ChannelId) types.Packet { + order := z.TokenOrderV2{ Sender: []byte(senderAddr.String()), Receiver: []byte("remote-receiver"), BaseToken: []byte("ugnot"), @@ -80,16 +102,12 @@ func main(cur realm) { Kind: z.TOKEN_ORDER_KIND_ESCROW, } - // In production the user attaches `-send 40ugnot`, which credits the proxy - // (the escrow account) and shows up in the OriginSend envelope. IssueCoins - // reproduces the deposit; SetOriginSend reproduces the envelope the impl - // reads to seed its escrow budget. proxy := zkgm.ProxyAddress() testing.IssueCoins(proxy, chain.NewCoins(chain.NewCoin("ugnot", 40))) testing.SetRealm(testing.NewUserRealm(senderAddr)) testing.SetOriginSend(chain.NewCoins(chain.NewCoin("ugnot", 40))) - sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(escrowOrder)) + sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) bk := banker.NewReadonlyBanker() ufmt.Printf("[INFO] send produced packet on channel: %s\n", sendPacket.SourceChannelId.String()) @@ -97,15 +115,19 @@ func main(cur realm) { ufmt.Println("[EXPECTED] send should succeed: attached 40ugnot covers the escrow order") ufmt.Println("[EXPECTED] proxy native escrow balance should be 40 (locked)") - // --- SCENARIO 3: ack — protocol-fill success is a no-op for an escrow --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 3. Acknowledge with protocol-fill success (no-op for escrow)") + return sendPacket +} + +// acknowledgeNativeEscrow acknowledges the sent packet with a protocol-fill success +// ack, which is a no-op for an escrow, so the native coins stay locked. +func acknowledgeNativeEscrow(cur realm, sendPacket types.Packet) { ack := mustSuccessAck(mustProtocolTokenOrderAck()) testing.SetRealm(testing.NewUserRealm(adminAddr)) core.PacketAcknowledgement(cross(cur), core.NewMsgPacketAcknowledgement([]types.Packet{sendPacket}, [][]byte{ack}, nil, 1)) - ufmt.Printf("[INFO] proxy native escrow balance: %d\n", bk.GetCoins(proxy).AmountOf("ugnot")) + bk := banker.NewReadonlyBanker() + ufmt.Printf("[INFO] proxy native escrow balance: %d\n", bk.GetCoins(zkgm.ProxyAddress()).AmountOf("ugnot")) ufmt.Println("[EXPECTED] proxy native escrow balance should be 40 (unchanged: escrow stays locked)") } diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_send_by_statelens_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_statelens_filetest.gno similarity index 80% rename from gno.land/r/onbloc/ibc/scenario/union/token_send_by_statelens_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_statelens_filetest.gno index 45151791..62ee4668 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_send_by_statelens_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_statelens_filetest.gno @@ -1,7 +1,7 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/send +package send -// token_send_by_statelens_filetest funds a sender, escrows (locks) a ucs03-zkgm +// lock_wrapped_voucher_by_statelens_filetest funds a sender, escrows (locks) a ucs03-zkgm // voucher, then acknowledges the sent packet with an acknowledgement proven by the // real state-lens/ics23-mpt light client, asserting the escrow stays locked. The // funding recv and the ack prove different commitments, so they use two consensus @@ -41,18 +41,35 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: open a state-lens channel and fund the sender --- - ufmt.Println("[SCENARIO] 1. Open a state-lens-backed channel and fund the sender via a proven recv") - testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.UpdateImpl(cross(cur), coreImplPath) - zkgm.UpdateImpl(cross(cur), zkgmImplPath) - zkgm.SetRateLimitDisabled(cross(cur), true) - zkgm.RegisterCoreApp(cross(cur)) + fx := buildSendFixture() - // The relayer-gated host entrypoints require RELAYER. Grant it to the admin so - // this single-actor scenario can drive the full flow. - access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + println("[SCENARIO] 1. Open a state-lens-backed channel and fund the sender via a proven recv") + clientId := openAndFundSender(cur, fx.fundRoot, fx.initPacket, fx.fundProof, fx.counterpartyChannel, fx.quoteToken) + println("") + println("[SCENARIO] 2. Send ESCROW order locking 40 of the voucher") + sendPacket := sendEscrowOrder(cur, fx.channelId, fx.quoteToken) + println("") + + println("[SCENARIO] 3. Acknowledge the sent packet with a state-lens MPT proof (escrow no-op)") + acknowledgeWithProof(cur, clientId, sendPacket, fx.quoteToken) +} + +// sendFixture holds the deterministic funding packet, its proof, and the storage +// root the scenario builds up front and threads through its steps. +type sendFixture struct { + channelId types.ChannelId + counterpartyChannel types.ChannelId + fundRoot []byte + initPacket types.Packet + fundProof []byte + quoteToken string +} + +// buildSendFixture builds the deterministic funding packet and the single-leaf +// EVM-MPT proof + storage root that commits it. The first channel opened is +// ChannelId(1), so the wrapped denom and the packet are known up front. +func buildSendFixture() sendFixture { channelId := types.ChannelId(1) counterpartyChannel := types.ChannelId(2) meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) @@ -68,11 +85,34 @@ func main(cur realm) { Metadata: meta, } initPacket := core.NewPacket(counterpartyChannel, channelId, mustPacketData(mustOrderInstruction(initOrder)), types.Timestamp(1<<62)) - - // Seed the client's (fund-height) consensus with the storage root that commits - // the funding packet, then open the channel. fundRoot, fundProof := buildMembershipProof(types.BatchPacketsPath(core.CommitPacketsHash([]types.Packet{initPacket})), commitmentMagic()) + return sendFixture{ + channelId: channelId, + counterpartyChannel: counterpartyChannel, + fundRoot: fundRoot, + initPacket: initPacket, + fundProof: fundProof, + quoteToken: quoteToken, + } +} + +// openAndFundSender installs the impls, registers the mock L1 and the real +// state-lens client (seeding its fund-height consensus with fundRoot), Force-opens +// the connection/channel, and receives the proven funding packet. It returns the +// state-lens client id. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func openAndFundSender(cur realm, fundRoot []byte, initPacket types.Packet, fundProof []byte, counterpartyChannel types.ChannelId, quoteToken string) types.ClientId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + clientState := &ics23mpt.ClientState{ L2ChainID: "l2-chain", L1ClientID: 1, @@ -127,10 +167,13 @@ func main(cur realm) { ufmt.Printf("[INFO] sender voucher balance after fund: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr)) ufmt.Println("[EXPECTED] sender voucher balance after fund should be 100") - // --- SCENARIO 2: send (escrow/lock) 40 of the voucher --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. Send ESCROW order locking 40 of the voucher") - escrowOrder := z.TokenOrderV2{ + return clientId +} + +// sendEscrowOrder sends an ESCROW TokenOrder that locks 40 of the voucher into the +// proxy escrow, and returns the produced packet for later acknowledgement. +func sendEscrowOrder(cur realm, channelId types.ChannelId, quoteToken string) types.Packet { + order := z.TokenOrderV2{ Sender: []byte(senderAddr.String()), Receiver: []byte("remote-receiver"), BaseToken: []byte(quoteToken), @@ -141,22 +184,25 @@ func main(cur realm) { } testing.SetRealm(testing.NewUserRealm(senderAddr)) - sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(escrowOrder)) - testing.SetRealm(testing.NewUserRealm(adminAddr)) + sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) ufmt.Printf("[INFO] sender voucher balance after send: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr)) ufmt.Printf("[INFO] proxy escrow balance after send: %d\n", zkgm.VoucherBalanceOf(quoteToken, zkgm.ProxyAddress())) ufmt.Println("[EXPECTED] sender voucher balance after send should be 60 (100 - 40 escrowed)") ufmt.Println("[EXPECTED] proxy escrow balance after send should be 40 (locked)") - // --- SCENARIO 3: acknowledge the sent packet, proven by the state-lens client --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 3. Acknowledge the sent packet with a state-lens MPT proof (escrow no-op)") + return sendPacket +} + +// acknowledgeWithProof adds the ack-height consensus via a crafted UpdateClient +// header, then acknowledges the sent packet with the inline state-lens MPT proof. +// The protocol-fill ack is a no-op for an escrow, so the lock holds. +func acknowledgeWithProof(cur realm, clientId types.ClientId, sendPacket types.Packet, quoteToken string) { ack := mustSuccessAck(mustProtocolTokenOrderAck()) ackCommitment := types.CommitAcks([][]byte{ack}) ackRoot, ackProof := buildMembershipProof(types.BatchReceiptsPath(core.CommitPacketsHash([]types.Packet{sendPacket})), ackCommitment[:]) - // Add the ack-height consensus state via a crafted UpdateClient header. + testing.SetRealm(testing.NewUserRealm(adminAddr)) header := ics23mpt.Header{ L1Height: fundHeight, L2Height: ackHeight, diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_send_by_statelens_real_cometbls_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_statelens_real_cometbls_filetest.gno similarity index 77% rename from gno.land/r/onbloc/ibc/scenario/union/token_send_by_statelens_real_cometbls_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_statelens_real_cometbls_filetest.gno index 459bef8d..9c23013e 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_send_by_statelens_real_cometbls_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_statelens_real_cometbls_filetest.gno @@ -1,7 +1,7 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/send +package send -// token_send_by_statelens_real_cometbls_filetest funds a sender, escrows (locks) +// lock_wrapped_voucher_by_statelens_real_cometbls_filetest funds a sender, escrows (locks) // a ucs03-zkgm voucher, then acknowledges the sent packet with an // acknowledgement proven by the real state-lens/ics23-mpt light client whose L1 // is a REAL cometbls light client (not a mock). @@ -52,17 +52,40 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: open a state-lens channel (real cometbls L1) and fund the sender --- - ufmt.Println("[SCENARIO] 1. Open a state-lens channel whose L1 is a REAL cometbls client and fund the sender") - testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.UpdateImpl(cross(cur), coreImplPath) - zkgm.UpdateImpl(cross(cur), zkgmImplPath) - zkgm.SetRateLimitDisabled(cross(cur), true) - zkgm.RegisterCoreApp(cross(cur)) - access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + fx := buildSendFixture() + + println("[SCENARIO] 1. Open a state-lens channel whose L1 is a REAL cometbls client and fund the sender") + clientId, l1ClientId := openAndFundSender(cur, fx.l1Contract, fx.fundRoot, fx.initPacket, fx.fundProof, fx.counterpartyChannel, fx.quoteToken) + println("") + println("[SCENARIO] 2. Send ESCROW order locking 40 of the voucher") + sendPacket := sendEscrowOrder(cur, fx.channelId, fx.quoteToken) + println("") + + println("[SCENARIO] 3. Acknowledge via state-lens, with the ack L2 consensus proven by the real cometbls L1") + acknowledgeWithCometblsProof(cur, fx.l1Contract, l1ClientId, clientId, sendPacket, fx.quoteToken) +} + +// sendFixture holds the deterministic funding packet, its proof, and the storage +// root the scenario builds up front and threads through its steps. +type sendFixture struct { + channelId types.ChannelId + counterpartyChannel types.ChannelId + l1Contract types.H256 + fundRoot []byte + initPacket types.Packet + fundProof []byte + quoteToken string +} + +// buildSendFixture builds the deterministic funding packet and the single-leaf +// EVM-MPT proof + storage root that commits it. The first channel opened is +// ChannelId(1) and a zero L1 contract address is used for the proof and the seeded +// client (they match), so the wrapped denom and the packet are known up front. +func buildSendFixture() sendFixture { channelId := types.ChannelId(1) counterpartyChannel := types.ChannelId(2) + var l1Contract types.H256 meta := tokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) initOrder := z.TokenOrderV2{ @@ -76,15 +99,40 @@ func main(cur realm) { Metadata: meta, } initPacket := core.NewPacket(counterpartyChannel, channelId, packetData(orderInstruction(initOrder)), types.Timestamp(1<<62)) - - // The funding consensus is seeded directly at state-lens creation, so the - // recv does not exercise the L1 (it only checks the L1 is Active via Status). + // The funding consensus is seeded directly at state-lens creation, so the recv + // does not exercise the L1 (it only checks the L1 is Active via Status). fundRoot, fundProof := buildMembershipProof(types.BatchPacketsPath(core.CommitPacketsHash([]types.Packet{initPacket})), commitmentMagic()) + return sendFixture{ + channelId: channelId, + counterpartyChannel: counterpartyChannel, + l1Contract: l1Contract, + fundRoot: fundRoot, + initPacket: initPacket, + fundProof: fundProof, + quoteToken: quoteToken, + } +} + +// openAndFundSender creates the real cometbls L1 client (placeholder root, id 1) +// and the state-lens L2 client (funding consensus, id 2), Force-opens the +// connection/channel, and receives the proven funding packet. It returns the +// state-lens client id and the L1 client id. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func openAndFundSender(cur realm, l1Contract types.H256, fundRoot []byte, initPacket types.Packet, fundProof []byte, counterpartyChannel types.ChannelId, quoteToken string) (types.ClientId, types.ClientId) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + // Create the real cometbls L1 client (id 1) with a placeholder root: it only // needs to be Active until the ack, when it is re-seeded to commit the ack // consensus (the ack receipt is not known until after Send). - var l1Contract types.H256 placeholderRoot := make([]byte, 32) l1CSBytes, l1ConsBytes := scenariocometbls.SeededClientBytes(l1Contract, l1Height, placeholderRoot) l1ClientType := types.ClientType(scenariocometbls.ClientType) @@ -121,10 +169,13 @@ func main(cur realm) { ufmt.Printf("[INFO] sender voucher balance after fund: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr)) ufmt.Println("[EXPECTED] sender voucher balance after fund should be 100") - // --- SCENARIO 2: send (escrow/lock) 40 of the voucher --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. Send ESCROW order locking 40 of the voucher") - escrowOrder := z.TokenOrderV2{ + return clientId, l1ClientId +} + +// sendEscrowOrder sends an ESCROW TokenOrder that locks 40 of the voucher into the +// proxy escrow, and returns the produced packet for later acknowledgement. +func sendEscrowOrder(cur realm, channelId types.ChannelId, quoteToken string) types.Packet { + order := z.TokenOrderV2{ Sender: []byte(senderAddr.String()), Receiver: []byte("remote-receiver"), BaseToken: []byte(quoteToken), @@ -135,17 +186,22 @@ func main(cur realm) { } testing.SetRealm(testing.NewUserRealm(senderAddr)) - sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, orderInstruction(escrowOrder)) - testing.SetRealm(testing.NewUserRealm(adminAddr)) + sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, orderInstruction(order)) ufmt.Printf("[INFO] sender voucher balance after send: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr)) ufmt.Printf("[INFO] proxy escrow balance after send: %d\n", zkgm.VoucherBalanceOf(quoteToken, zkgm.ProxyAddress())) ufmt.Println("[EXPECTED] sender voucher balance after send should be 60 (100 - 40 escrowed)") ufmt.Println("[EXPECTED] proxy escrow balance after send should be 40 (locked)") - // --- SCENARIO 3: acknowledge the sent packet, proven through the real cometbls L1 --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 3. Acknowledge via state-lens, with the ack L2 consensus proven by the real cometbls L1") + return sendPacket +} + +// acknowledgeWithCometblsProof builds the ack L2 consensus and the inline L1 +// membership proof committing it, re-seeds the L1 so its consensus root matches +// (ForceUpdateClient), adds the L2 consensus via UpdateClient (driving the genuine +// cometbls VerifyMembership), then acknowledges the sent packet. The protocol-fill +// ack is a no-op for an escrow, so the lock holds. +func acknowledgeWithCometblsProof(cur realm, l1Contract types.H256, l1ClientId, clientId types.ClientId, sendPacket types.Packet, quoteToken string) { ack := fixture.SuccessAck(fixture.ProtocolFillAck()) ackCommitment := types.CommitAcks([][]byte{ack}) ackRoot, ackProof := buildMembershipProof(types.BatchReceiptsPath(core.CommitPacketsHash([]types.Packet{sendPacket})), ackCommitment[:]) @@ -156,6 +212,8 @@ func main(cur realm) { l2AckConsensus := makeConsensusBytes(2, make([]byte, 32), ackRoot) l1Proof, l1Root := scenariocometbls.ProveConsensus(l1Contract, types.ClientId(l2ClientID), ackHeight, l2AckConsensus) reseedCSBytes, reseedConsBytes := scenariocometbls.SeededClientBytes(l1Contract, l1Height, l1Root) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) core.ForceUpdateClient(cross(cur), types.NewMsgForceUpdateClient(l1ClientId, reseedCSBytes, reseedConsBytes)) header := ics23mpt.Header{ diff --git a/gno.land/r/onbloc/ibc/scenario/union/token_send_by_ucs03_zkgm_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_ucs03_zkgm_filetest.gno similarity index 80% rename from gno.land/r/onbloc/ibc/scenario/union/token_send_by_ucs03_zkgm_filetest.gno rename to gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_ucs03_zkgm_filetest.gno index 71584158..05c71326 100644 --- a/gno.land/r/onbloc/ibc/scenario/union/token_send_by_ucs03_zkgm_filetest.gno +++ b/gno.land/r/onbloc/ibc/scenario/union/send/lock_wrapped_voucher_by_ucs03_zkgm_filetest.gno @@ -1,7 +1,7 @@ -// PKGPATH: gno.land/r/onbloc/ibc/scenario/union -package union +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/send +package send -// token_send_by_ucs03_zkgm_filetest walks a full ucs03-zkgm token send through the +// lock_wrapped_voucher_by_ucs03_zkgm_filetest walks a full ucs03-zkgm token send through the // upgradeable union IBC host (permissive mock light client) and asserts the escrowed // token stays locked in the proxy after the acknowledgement. @@ -32,17 +32,39 @@ const ( ) func main(cur realm) { - // --- SCENARIO 1: bootstrap (admin) — kept inline so each core call is a - // direct origin call: runtime.AssertOriginCall requires <= 2 call frames. --- - ufmt.Println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + println("[SCENARIO] 1. Bootstrap IBC host and open client/connection/channel") + channelId := bootstrap(cur) + println("") + + // The wrapped denom is deterministic for (path=0, channel, base=ugnot, image), + // so it is derived once here and reused by the recv funding and the send below. + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Fund sender with wrapped voucher via INITIALIZE recv (amount 100)") + fundSenderViaInitialize(cur, channelId, quoteToken, meta) + println("") + + println("[SCENARIO] 3. Send ESCROW order locking 40 of the voucher") + sendPacket := sendEscrowOrder(cur, channelId, quoteToken) + println("") + + println("[SCENARIO] 4. Acknowledge with protocol-fill success (no-op for escrow)") + acknowledgeEscrow(cur, sendPacket, quoteToken) +} + +// bootstrap installs the core/zkgm impls, grants the admin the relayer role, and +// opens a client/connection/channel backed by the permissive mock light client. +// +// It is kept inline (not split further): every admin/relayer core entrypoint +// authorizes the caller via cur.Previous(), so testing.SetRealm and the cross(cur) +// call must run in the same frame for the admin user to be seen as the caller. +func bootstrap(cur realm) types.ChannelId { testing.SetRealm(testing.NewUserRealm(adminAddr)) core.UpdateImpl(cross(cur), coreImplPath) zkgm.UpdateImpl(cross(cur), zkgmImplPath) zkgm.SetRateLimitDisabled(cross(cur), true) zkgm.RegisterCoreApp(cross(cur)) - - // The relayer-gated host entrypoints require RELAYER. Grant it to the admin so - // this single-actor scenario can drive the full flow. access.GrantRole(cross(cur), access.RelayerRole, adminAddr) core.RegisterClient(cross(cur), mockClientType, func(_, _ []byte) (lightclient.Interface, error) { @@ -59,17 +81,19 @@ func main(cur realm) { core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) channelId := types.ChannelId(1) core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + ufmt.Printf("[INFO] handshake opened: client=%s connection=%s channel=%s\n", clientId.String(), connectionId.String(), channelId.String()) ufmt.Println("[EXPECTED] client should be 1") ufmt.Println("[EXPECTED] connection should be 1") ufmt.Println("[EXPECTED] channel should be 1") - // --- SCENARIO 2: fund the sender with a wrapped voucher via an INITIALIZE recv --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 2. Fund sender with wrapped voucher via INITIALIZE recv (amount 100)") - meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) - quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) - initOrder := z.TokenOrderV2{ + return channelId +} + +// fundSenderViaInitialize mints 100 of the wrapped voucher to the sender by +// receiving an INITIALIZE TokenOrder addressed to it. +func fundSenderViaInitialize(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ Sender: []byte("remote-sender"), Receiver: []byte(senderAddr.String()), BaseToken: []byte("ugnot"), @@ -79,10 +103,10 @@ func main(cur realm) { Kind: z.TOKEN_ORDER_KIND_INITIALIZE, Metadata: meta, } - initPacket := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(initOrder)), types.Timestamp(1<<62)) + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) testing.SetRealm(testing.NewUserRealm(adminAddr)) - core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{initPacket}, [][]byte{nil}, nil, 1)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) // Balances are read back through the proxy's VoucherBalanceOf, the stable public // surface for wrapped-voucher balances (proxy-owned escrow amount). @@ -91,11 +115,12 @@ func main(cur realm) { ufmt.Printf("[INFO] minted to sender %s, balance: %d\n", senderAddr.String(), zkgm.VoucherBalanceOf(quoteToken, senderAddr)) ufmt.Println("[EXPECTED] minted token should be the ibc/ wrapped voucher of base ugnot") ufmt.Println("[EXPECTED] sender voucher balance should be 100 (full INITIALIZE amount minted)") +} - // --- SCENARIO 3: send the ESCROW order that locks 40 of the voucher --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 3. Send ESCROW order locking 40 of the voucher") - escrowOrder := z.TokenOrderV2{ +// sendEscrowOrder sends an ESCROW TokenOrder that locks 40 of the voucher into the +// proxy escrow, and returns the produced packet for later acknowledgement. +func sendEscrowOrder(cur realm, channelId types.ChannelId, quoteToken string) types.Packet { + order := z.TokenOrderV2{ Sender: []byte(senderAddr.String()), Receiver: []byte("remote-receiver"), BaseToken: []byte(quoteToken), @@ -106,7 +131,7 @@ func main(cur realm) { } testing.SetRealm(testing.NewUserRealm(senderAddr)) - sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(escrowOrder)) + sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) ufmt.Printf("[INFO] locked token (escrowed into proxy): %s\n", quoteToken) ufmt.Printf("[INFO] locked into proxy escrow %s\n", zkgm.ProxyAddress().String()) @@ -116,9 +141,12 @@ func main(cur realm) { ufmt.Println("[EXPECTED] sender voucher balance should be 60 (100 - 40 escrowed)") ufmt.Println("[EXPECTED] proxy escrow balance should be 40 (locked)") - // --- SCENARIO 4: ack — protocol-fill success is a no-op for an escrow, so the lock holds --- - ufmt.Println("") - ufmt.Println("[SCENARIO] 4. Acknowledge with protocol-fill success (no-op for escrow)") + return sendPacket +} + +// acknowledgeEscrow acknowledges the sent packet with a protocol-fill success ack, +// which is a no-op for an escrow, so the lock holds. +func acknowledgeEscrow(cur realm, sendPacket types.Packet, quoteToken string) { ack := mustSuccessAck(mustProtocolTokenOrderAck()) testing.SetRealm(testing.NewUserRealm(adminAddr)) diff --git a/gno.land/r/onbloc/ibc/scenario/union/settlement/ack_failure_refund_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/settlement/ack_failure_refund_filetest.gno new file mode 100644 index 00000000..7dc1e2bc --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/settlement/ack_failure_refund_filetest.gno @@ -0,0 +1,197 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/settlement +package settlement + +// ack_failure_refund_filetest is the BY-TYPE settlement scenario for the failure-ack +// refund (re-targeted from the legacy e2e zs23, refund branch). A sender escrows a +// voucher into the proxy on send; when the counterparty returns a FAILURE +// acknowledgement, the escrow is refunded to the sender — the voucher moves back +// from the proxy to the sender and the proxy escrow returns to zero. Both sides of +// the refund are verified as balance diffs. (A protocol-success ack instead leaves +// the escrow settled — that no-op branch is covered by the send/ lock tests.) + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + senderAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Fund the sender with 100 of the voucher via an INITIALIZE recv") + fundSender(cur, channelId, quoteToken, meta) + println("") + + println("[SCENARIO] 3. Send an ESCROW order locking 40 into the proxy") + sendPacket := sendEscrow(cur, channelId, quoteToken) + println("") + + println("[SCENARIO] 4. A FAILURE acknowledgement refunds the escrow to the sender") + failureAckRefund(cur, sendPacket, quoteToken) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +func fundSender(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(senderAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(100), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + ufmt.Printf("[INFO] sender voucher balance: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr)) + ufmt.Println("[EXPECTED] sender should hold 100") +} + +func sendEscrow(cur realm, channelId types.ChannelId, quoteToken string) types.Packet { + order := z.TokenOrderV2{ + Sender: []byte(senderAddr.String()), + Receiver: []byte("remote-receiver"), + BaseToken: []byte(quoteToken), + BaseAmount: u256.NewUint(40), + QuoteToken: []byte("ugnot"), + QuoteAmount: u256.NewUint(40), + Kind: z.TOKEN_ORDER_KIND_ESCROW, + } + + testing.SetRealm(testing.NewUserRealm(senderAddr)) + sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) + + ufmt.Printf("[INFO] sender voucher balance: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr)) + ufmt.Printf("[INFO] proxy escrow balance: %d\n", zkgm.VoucherBalanceOf(quoteToken, zkgm.ProxyAddress())) + ufmt.Println("[EXPECTED] sender 100 -> 60, proxy escrow 0 -> 40") + return sendPacket +} + +func failureAckRefund(cur realm, sendPacket types.Packet, quoteToken string) { + senderBefore := zkgm.VoucherBalanceOf(quoteToken, senderAddr) + proxyBefore := zkgm.VoucherBalanceOf(quoteToken, zkgm.ProxyAddress()) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketAcknowledgement(cross(cur), core.NewMsgPacketAcknowledgement([]types.Packet{sendPacket}, [][]byte{failureAck()}, nil, 1)) + + senderAfter := zkgm.VoucherBalanceOf(quoteToken, senderAddr) + proxyAfter := zkgm.VoucherBalanceOf(quoteToken, zkgm.ProxyAddress()) + ufmt.Printf("[INFO] sender voucher balance: %d -> %d (delta +%d)\n", senderBefore, senderAfter, senderAfter-senderBefore) + ufmt.Printf("[INFO] proxy escrow balance: %d -> %d (delta %d)\n", proxyBefore, proxyAfter, proxyAfter-proxyBefore) + ufmt.Println("[EXPECTED] failure ack refunds 40: sender 60 -> 100, proxy escrow 40 -> 0") +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +func failureAck() []byte { + ack, err := z.EncodeAck(z.Ack{Tag: new(u256.Uint).SetBytes(z.TAG_ACK_FAILURE[:])}) + if err != nil { + panic(err) + } + return ack +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Fund the sender with 100 of the voucher via an INITIALIZE recv +// [INFO] sender voucher balance: 100 +// [EXPECTED] sender should hold 100 +// +// [SCENARIO] 3. Send an ESCROW order locking 40 into the proxy +// [INFO] sender voucher balance: 60 +// [INFO] proxy escrow balance: 40 +// [EXPECTED] sender 100 -> 60, proxy escrow 0 -> 40 +// +// [SCENARIO] 4. A FAILURE acknowledgement refunds the escrow to the sender +// [INFO] sender voucher balance: 60 -> 100 (delta +40) +// [INFO] proxy escrow balance: 40 -> 0 (delta -40) +// [EXPECTED] failure ack refunds 40: sender 60 -> 100, proxy escrow 40 -> 0 diff --git a/gno.land/r/onbloc/ibc/scenario/union/settlement/duplicate_recv_noop_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/settlement/duplicate_recv_noop_filetest.gno new file mode 100644 index 00000000..6a5985f2 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/settlement/duplicate_recv_noop_filetest.gno @@ -0,0 +1,175 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/settlement +package settlement + +// duplicate_recv_noop_filetest is the BY-TYPE settlement scenario for receive +// idempotency (re-targeted from the legacy e2e zs14a). A packet is received once, +// minting the wrapped voucher and recording the receipt; receiving the *same* +// packet again is a no-op — the receipt stays recorded and the balance does not +// change. The second receive must neither panic nor double-mint. + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(initOrder(quoteToken, meta))), types.Timestamp(1<<62)) + + println("[SCENARIO] 2. First receive mints the voucher and records the receipt") + firstRecv(cur, packet, quoteToken) + println("") + + println("[SCENARIO] 3. Receiving the same packet again is a no-op (idempotent)") + duplicateRecv(cur, packet, quoteToken) +} + +// bootstrap installs the impls, grants the relayer role, and opens a client/ +// connection/channel backed by the shared permissive mock light client. +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + // The shared mock LC realm self-registers via core.RegisterClient, so it is the + // caller there — grant RELAYER to the mock realm's own address too. + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +func initOrder(quoteToken string, meta []byte) z.TokenOrderV2 { + return z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(100), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } +} + +func firstRecv(cur realm, packet types.Packet, quoteToken string) { + before := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + after := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + ufmt.Printf("[INFO] receiver voucher balance: %d -> %d (delta +%d)\n", before, after, after-before) + ufmt.Printf("[INFO] packet receipt recorded: %t\n", receiptRecorded(packet)) + ufmt.Println("[EXPECTED] first receive should mint 100 and record the receipt") +} + +func duplicateRecv(cur realm, packet types.Packet, quoteToken string) { + before := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + after := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + ufmt.Printf("[INFO] receiver voucher balance: %d -> %d (delta +%d)\n", before, after, after-before) + ufmt.Printf("[INFO] packet receipt still recorded: %t\n", receiptRecorded(packet)) + ufmt.Println("[EXPECTED] duplicate receive should be a no-op: balance unchanged, receipt still recorded") +} + +// receiptRecorded re-targets the removed core.HasPacketReceipt to the current +// GetBatchReceipts getter: a recorded receipt resolves without error. +func receiptRecorded(packet types.Packet) bool { + _, err := core.GetBatchReceipts(core.CommitPacketsHash([]types.Packet{packet})) + return err == nil +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. First receive mints the voucher and records the receipt +// [INFO] receiver voucher balance: 0 -> 100 (delta +100) +// [INFO] packet receipt recorded: true +// [EXPECTED] first receive should mint 100 and record the receipt +// +// [SCENARIO] 3. Receiving the same packet again is a no-op (idempotent) +// [INFO] receiver voucher balance: 100 -> 100 (delta +0) +// [INFO] packet receipt still recorded: true +// [EXPECTED] duplicate receive should be a no-op: balance unchanged, receipt still recorded diff --git a/gno.land/r/onbloc/ibc/scenario/union/settlement/fee_distribution_on_recv_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/settlement/fee_distribution_on_recv_filetest.gno new file mode 100644 index 00000000..5812e949 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/settlement/fee_distribution_on_recv_filetest.gno @@ -0,0 +1,148 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/settlement +package settlement + +// fee_distribution_on_recv_filetest is the NORMAL-path settlement scenario for the +// relayer fee split on receive (re-targeted from the legacy e2e zs22, voucher +// half). When a received TokenOrder's QuoteAmount is less than its BaseAmount, the +// receiver is minted the QuoteAmount and the relayer (the PacketRecv caller) is +// minted the difference as its fee. Both sides of the split are verified as balance +// diffs. (The legacy native-unescrow fee half depends on the send/native escrow +// path and is covered separately.) + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + // adminAddr is the bootstrap admin and the relayer that drives PacketRecv, so it + // is the fee recipient for the split below. + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Fee Token", Symbol: "FEE", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ufee"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Receive an order with QuoteAmount < BaseAmount: receiver gets the quote, relayer keeps the fee") + receiveWithFee(cur, channelId, quoteToken, meta) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +func receiveWithFee(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ufee"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(88), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + recvBefore := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + feeBefore := zkgm.VoucherBalanceOf(quoteToken, adminAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) // admin is the relayer / fee recipient + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + recvAfter := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + feeAfter := zkgm.VoucherBalanceOf(quoteToken, adminAddr) + + ufmt.Printf("[INFO] receiver voucher balance: %d -> %d (delta +%d)\n", recvBefore, recvAfter, recvAfter-recvBefore) + ufmt.Printf("[INFO] relayer fee voucher balance: %d -> %d (delta +%d)\n", feeBefore, feeAfter, feeAfter-feeBefore) + ufmt.Println("[EXPECTED] receiver should get 88 (quote) and the relayer should keep 12 (base - quote)") +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Receive an order with QuoteAmount < BaseAmount: receiver gets the quote, relayer keeps the fee +// [INFO] receiver voucher balance: 0 -> 88 (delta +88) +// [INFO] relayer fee voucher balance: 0 -> 12 (delta +12) +// [EXPECTED] receiver should get 88 (quote) and the relayer should keep 12 (base - quote) diff --git a/gno.land/r/onbloc/ibc/scenario/union/settlement/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/settlement/gnomod.toml new file mode 100644 index 00000000..9395410f --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/settlement/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/settlement" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/settlement/initialize_then_escrow_voucher_lifecycle_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/settlement/initialize_then_escrow_voucher_lifecycle_filetest.gno new file mode 100644 index 00000000..5f03455c --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/settlement/initialize_then_escrow_voucher_lifecycle_filetest.gno @@ -0,0 +1,175 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/settlement +package settlement + +// initialize_then_escrow_voucher_lifecycle_filetest is the NORMAL-path settlement +// scenario for the wrapped-voucher lifecycle (re-targeted from the legacy e2e +// zs13). An INITIALIZE order deploys the wrapped token and mints its amount; a +// following ESCROW order for the same asset mints more into the existing voucher. +// Each step is verified as a balance diff plus a recorded receipt. (The legacy +// `zkgm.GetTokenOrigin` introspection is now store-internal, so origin tracking is +// not asserted here — the minted balance is the observable that matters.) + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. INITIALIZE order: deploy the wrapped token and mint 33") + receiveOrder(cur, channelId, "INITIALIZE", initializeOrder(quoteToken, meta), quoteToken, 33) + println("") + + println("[SCENARIO] 3. ESCROW order: mint 21 more into the existing voucher") + receiveOrder(cur, channelId, "ESCROW", escrowOrder(quoteToken), quoteToken, 54) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +func initializeOrder(quoteToken string, meta []byte) z.TokenOrderV2 { + return z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(33), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(33), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } +} + +func escrowOrder(quoteToken string) z.TokenOrderV2 { + return z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(21), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(21), + Kind: z.TOKEN_ORDER_KIND_ESCROW, + } +} + +// receiveOrder receives one TokenOrder and reports the receiver's voucher balance +// as a before/after diff plus the recorded receipt; expectedTotal is the asserted +// cumulative balance after this order. +func receiveOrder(cur realm, channelId types.ChannelId, kind string, order z.TokenOrderV2, quoteToken string, expectedTotal int64) { + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + before := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + + after := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + ufmt.Printf("[INFO] %s: receiver voucher balance %d -> %d (delta +%d)\n", kind, before, after, after-before) + ufmt.Printf("[INFO] %s: packet receipt recorded: %t\n", kind, receiptRecorded(packet)) + ufmt.Printf("[EXPECTED] cumulative voucher balance should be %d\n", expectedTotal) +} + +func receiptRecorded(packet types.Packet) bool { + _, err := core.GetBatchReceipts(core.CommitPacketsHash([]types.Packet{packet})) + return err == nil +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. INITIALIZE order: deploy the wrapped token and mint 33 +// [INFO] INITIALIZE: receiver voucher balance 0 -> 33 (delta +33) +// [INFO] INITIALIZE: packet receipt recorded: true +// [EXPECTED] cumulative voucher balance should be 33 +// +// [SCENARIO] 3. ESCROW order: mint 21 more into the existing voucher +// [INFO] ESCROW: receiver voucher balance 33 -> 54 (delta +21) +// [INFO] ESCROW: packet receipt recorded: true +// [EXPECTED] cumulative voucher balance should be 54 diff --git a/gno.land/r/onbloc/ibc/scenario/union/settlement/send_success_ack_lifecycle_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/settlement/send_success_ack_lifecycle_filetest.gno new file mode 100644 index 00000000..1e7475c3 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/settlement/send_success_ack_lifecycle_filetest.gno @@ -0,0 +1,199 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/settlement +package settlement + +// send_success_ack_lifecycle_filetest is the NORMAL-path settlement scenario for the +// send → acknowledge packet lifecycle (re-targeted from the legacy e2e zs11/z23). +// A voucher ESCROW send writes a packet commitment (verified via the current +// core.GetBatchPackets getter, since the legacy HasPacketCommitment/ +// HasAcknowledgement getters were removed) and locks the voucher in the proxy. A +// protocol-success acknowledgement is a no-op for an escrow: the locked balances +// settle unchanged. + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + senderAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Fund the sender with 100 of the voucher via an INITIALIZE recv") + fundSender(cur, channelId, quoteToken, meta) + println("") + + println("[SCENARIO] 3. ESCROW send writes a packet commitment and locks 40") + sendPacket := sendEscrow(cur, channelId, quoteToken) + println("") + + println("[SCENARIO] 4. A protocol-success ack settles the escrow (protocol-fill no-op)") + successAck(cur, sendPacket, quoteToken) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +func fundSender(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(senderAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(100), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + ufmt.Printf("[INFO] sender voucher balance: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr)) + ufmt.Println("[EXPECTED] sender should hold 100") +} + +func sendEscrow(cur realm, channelId types.ChannelId, quoteToken string) types.Packet { + order := z.TokenOrderV2{ + Sender: []byte(senderAddr.String()), + Receiver: []byte("remote-receiver"), + BaseToken: []byte(quoteToken), + BaseAmount: u256.NewUint(40), + QuoteToken: []byte("ugnot"), + QuoteAmount: u256.NewUint(40), + Kind: z.TOKEN_ORDER_KIND_ESCROW, + } + + testing.SetRealm(testing.NewUserRealm(senderAddr)) + sendPacket := zkgm.Send(cross(cur), channelId, types.Timestamp(1<<62), [32]byte{}, mustOrderInstruction(order)) + + ufmt.Printf("[INFO] sender voucher balance: %d, proxy escrow: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr), zkgm.VoucherBalanceOf(quoteToken, zkgm.ProxyAddress())) + ufmt.Printf("[INFO] packet commitment present after send: %t\n", committed(sendPacket)) + ufmt.Println("[EXPECTED] sender 100 -> 60, proxy escrow 40, commitment present") + return sendPacket +} + +func successAck(cur realm, sendPacket types.Packet, quoteToken string) { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketAcknowledgement(cross(cur), core.NewMsgPacketAcknowledgement([]types.Packet{sendPacket}, [][]byte{successAckBytes()}, nil, 1)) + + ufmt.Printf("[INFO] sender voucher balance: %d, proxy escrow: %d\n", zkgm.VoucherBalanceOf(quoteToken, senderAddr), zkgm.VoucherBalanceOf(quoteToken, zkgm.ProxyAddress())) + ufmt.Println("[EXPECTED] protocol-success ack is a no-op for an escrow: balances settle unchanged (sender 60, proxy 40)") +} + +func committed(packet types.Packet) bool { + _, err := core.GetBatchPackets(core.CommitPacketsHash([]types.Packet{packet})) + return err == nil +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +func successAckBytes() []byte { + inner, err := z.EncodeTokenOrderAck(z.TokenOrderAck{FillType: new(u256.Uint).SetBytes(z.FILL_TYPE_PROTOCOL[:])}) + if err != nil { + panic(err) + } + ack, err := z.EncodeAck(z.Ack{Tag: new(u256.Uint).SetBytes(z.TAG_ACK_SUCCESS[:]), InnerAck: inner}) + if err != nil { + panic(err) + } + return ack +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Fund the sender with 100 of the voucher via an INITIALIZE recv +// [INFO] sender voucher balance: 100 +// [EXPECTED] sender should hold 100 +// +// [SCENARIO] 3. ESCROW send writes a packet commitment and locks 40 +// [INFO] sender voucher balance: 60, proxy escrow: 40 +// [INFO] packet commitment present after send: true +// [EXPECTED] sender 100 -> 60, proxy escrow 40, commitment present +// +// [SCENARIO] 4. A protocol-success ack settles the escrow (protocol-fill no-op) +// [INFO] sender voucher balance: 60, proxy escrow: 40 +// [EXPECTED] protocol-success ack is a no-op for an escrow: balances settle unchanged (sender 60, proxy 40) diff --git a/gno.land/r/onbloc/ibc/scenario/union/upgrade/gnomod.toml b/gno.land/r/onbloc/ibc/scenario/union/upgrade/gnomod.toml new file mode 100644 index 00000000..397cf4e1 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/upgrade/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/scenario/union/upgrade" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/union/upgrade/reject_non_admin_update_impl_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/upgrade/reject_non_admin_update_impl_filetest.gno new file mode 100644 index 00000000..8b099842 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/upgrade/reject_non_admin_update_impl_filetest.gno @@ -0,0 +1,33 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/upgrade +package upgrade + +// reject_non_admin_update_impl_filetest is an EXCEPTION-path upgrade scenario for +// the current admin-gated impl model. zkgm.UpdateImpl is gated by the access +// manager on the "update_impl" selector (defaulting to AdminRole). A non-admin +// caller cannot install or re-point the impl — the terminating panic matched by the +// // Error: directive. (This replaces the legacy allowed-impls "removed/unallowed +// impl rejected" and "bootstrap outside namespace" tests under the current model.) + +import ( + "testing" + + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" +) + +const ( + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + nonAdminAddr = address("g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu") // holds no role +) + +func main(cur realm) { + println("[SCENARIO] 1. A non-admin attempts to install the impl -> rejected") + testing.SetRealm(testing.NewUserRealm(nonAdminAddr)) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) +} + +// Output: +// [SCENARIO] 1. A non-admin attempts to install the impl -> rejected + +// Error: +// access manager unauthorized call: g1dyxy88p94acjnm8dmu9tfj2mv2ncvx83cagllu is not authorized to call update_impl on gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm diff --git a/gno.land/r/onbloc/ibc/scenario/union/upgrade/reject_unregistered_impl_path_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/upgrade/reject_unregistered_impl_path_filetest.gno new file mode 100644 index 00000000..ec92bc69 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/upgrade/reject_unregistered_impl_path_filetest.gno @@ -0,0 +1,33 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/upgrade +package upgrade + +// reject_unregistered_impl_path_filetest is an EXCEPTION-path upgrade scenario for +// the current admin-gated impl model. UpdateImpl can only install a path whose +// constructor was registered by that impl's init (RegisterImpl). Installing an +// arbitrary, unregistered path is rejected — the terminating panic matched by the +// // Error: directive. (This replaces the legacy allowed-impls "unallowed impl" +// test, whose allowlist model was removed.) + +import ( + "testing" + + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" +) + +const ( + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + unregisteredPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v99" +) + +func main(cur realm) { + println("[SCENARIO] 1. The admin installs an impl at an unregistered path -> rejected") + testing.SetRealm(testing.NewUserRealm(adminAddr)) + zkgm.UpdateImpl(cross(cur), unregisteredPath) +} + +// Output: +// [SCENARIO] 1. The admin installs an impl at an unregistered path -> rejected + +// Error: +// impl constructor not found diff --git a/gno.land/r/onbloc/ibc/scenario/union/upgrade/state_survives_impl_reinstall_filetest.gno b/gno.land/r/onbloc/ibc/scenario/union/upgrade/state_survives_impl_reinstall_filetest.gno new file mode 100644 index 00000000..2c34e660 --- /dev/null +++ b/gno.land/r/onbloc/ibc/scenario/union/upgrade/state_survives_impl_reinstall_filetest.gno @@ -0,0 +1,156 @@ +// PKGPATH: gno.land/r/onbloc/ibc/scenario/union/upgrade +package upgrade + +// state_survives_impl_reinstall_filetest is the NORMAL-path upgrade scenario for +// the current admin-gated impl model (redesigned from the legacy allowed-impls +// continuity tests, whose NewUpdateRequest/allowlist API was removed). The current +// model is `zkgm.UpdateImpl(cur, path)`: admin-gated, requiring a constructor +// registered by the impl's init. UpdateImpl rebuilds the impl against the SAME +// proxy-owned store, so persistent state survives a re-install. This is verified by +// minting a voucher, re-installing the impl, and confirming the balance persists. + +import ( + "chain" + "testing" + + "gno.land/p/nt/ufmt/v0" + types "gno.land/p/onbloc/ibc/union/types" + z "gno.land/p/onbloc/ibc/union/zkgm" + + u256 "gno.land/p/gnoswap/uint256" + + "gno.land/r/onbloc/ibc/union/access" + zkgm "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm" + _ "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + core "gno.land/r/onbloc/ibc/union/core" + _ "gno.land/r/onbloc/ibc/union/core/v1" + mocklc "gno.land/r/onbloc/ibc/testing/mock/lightclient" +) + +const ( + coreImplPath = "gno.land/r/onbloc/ibc/union/core/v1" + zkgmImplPath = "gno.land/r/onbloc/ibc/union/apps/ucs03_zkgm/v1" + mockLcPkgPath = "gno.land/r/onbloc/ibc/testing/mock/lightclient" + + adminAddr = address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + receiverAddr = address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm") +) + +func main(cur realm) { + println("[SCENARIO] 1. Bootstrap IBC host and open a zkgm channel") + channelId := bootstrap(cur) + println("") + + meta := mustTokenMetadata("grc20", z.TokenInitializer{Name: "Gno Token", Symbol: "GNOT", Decimals: 6}) + quoteToken := z.PredictWrappedTokenV2(u256.Zero(), uint32(channelId), []byte("ugnot"), z.MetadataImage(mustDecodeMeta(meta))) + + println("[SCENARIO] 2. Mint a voucher under the installed impl") + mint(cur, channelId, quoteToken, meta) + println("") + + println("[SCENARIO] 3. Re-install the impl: persistent state survives the rebuild") + reinstallImpl(cur, quoteToken) +} + +func bootstrap(cur realm) types.ChannelId { + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.UpdateImpl(cross(cur), coreImplPath) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) + zkgm.SetRateLimitDisabled(cross(cur), true) + zkgm.RegisterCoreApp(cross(cur)) + access.GrantRole(cross(cur), access.RelayerRole, adminAddr) + access.GrantRole(cross(cur), access.RelayerRole, chain.PackageAddress(mockLcPkgPath)) + + mocklc.RegisterMockLightClient(cross(cur)) + core.CreateClient(cross(cur), core.NewMsgCreateClient(mocklc.MockClientType, nil, nil)) + clientId := types.ClientId(1) + + core.ConnectionOpenInit(cross(cur), core.NewMsgConnectionOpenInit(clientId, types.ClientId(99))) + connectionId := types.ConnectionId(1) + core.ConnectionOpenAck(cross(cur), core.NewMsgConnectionOpenAck(connectionId, types.ConnectionId(77), nil, 1)) + + portId := []byte(zkgm.ProxyPkgPath()) + core.ChannelOpenInit(cross(cur), core.NewMsgChannelOpenInit(portId, portId, connectionId, zkgm.Version, "g1relayer")) + channelId := types.ChannelId(1) + core.ChannelOpenAck(cross(cur), core.NewMsgChannelOpenAck(channelId, zkgm.Version, types.ChannelId(2), nil, 1, "g1relayer")) + return channelId +} + +func mint(cur realm, channelId types.ChannelId, quoteToken string, meta []byte) { + order := z.TokenOrderV2{ + Sender: []byte("remote-sender"), + Receiver: []byte(receiverAddr.String()), + BaseToken: []byte("ugnot"), + BaseAmount: u256.NewUint(100), + QuoteToken: []byte(quoteToken), + QuoteAmount: u256.NewUint(100), + Kind: z.TOKEN_ORDER_KIND_INITIALIZE, + Metadata: meta, + } + packet := core.NewPacket(types.ChannelId(2), channelId, mustPacketData(mustOrderInstruction(order)), types.Timestamp(1<<62)) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + core.PacketRecv(cross(cur), core.NewMsgPacketRecv([]types.Packet{packet}, [][]byte{nil}, nil, 1)) + ufmt.Printf("[INFO] receiver voucher balance: %d\n", zkgm.VoucherBalanceOf(quoteToken, receiverAddr)) + ufmt.Println("[EXPECTED] receiver should hold 100") +} + +func reinstallImpl(cur realm, quoteToken string) { + before := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + + testing.SetRealm(testing.NewUserRealm(adminAddr)) + zkgm.UpdateImpl(cross(cur), zkgmImplPath) // re-point UpdateImpl to the same registered path + + after := zkgm.VoucherBalanceOf(quoteToken, receiverAddr) + ufmt.Printf("[INFO] receiver voucher balance across re-install: %d -> %d\n", before, after) + ufmt.Println("[EXPECTED] the balance should persist (impl rebuilt against the same store)") +} + +// --- encoding helpers --- + +func mustOrderInstruction(order z.TokenOrderV2) z.Instruction { + operand, err := z.EncodeTokenOrderV2(order) + if err != nil { + panic(err) + } + return z.Instruction{Version: z.INSTR_VERSION_2, Opcode: z.OP_TOKEN_ORDER, Operand: operand} +} + +func mustPacketData(instr z.Instruction) []byte { + data, err := z.EncodeZkgmPacket(z.ZkgmPacket{Path: u256.Zero(), Instruction: instr}) + if err != nil { + panic(err) + } + return data +} + +func mustTokenMetadata(implementation string, ti z.TokenInitializer) []byte { + initBytes, err := z.EncodeTokenInitializer(ti) + if err != nil { + panic(err) + } + meta, err := z.EncodeTokenMetadata(z.TokenMetadata{Implementation: []byte(implementation), Initializer: initBytes}) + if err != nil { + panic(err) + } + return meta +} + +func mustDecodeMeta(bz []byte) z.TokenMetadata { + meta, err := z.DecodeTokenMetadata(bz) + if err != nil { + panic(err) + } + return meta +} + +// Output: +// [SCENARIO] 1. Bootstrap IBC host and open a zkgm channel +// +// [SCENARIO] 2. Mint a voucher under the installed impl +// [INFO] receiver voucher balance: 100 +// [EXPECTED] receiver should hold 100 +// +// [SCENARIO] 3. Re-install the impl: persistent state survives the rebuild +// [INFO] receiver voucher balance across re-install: 100 -> 100 +// [EXPECTED] the balance should persist (impl rebuilt against the same store) diff --git a/gno.land/r/onbloc/ibc/testing/mock/receiver/gnomod.toml b/gno.land/r/onbloc/ibc/testing/mock/receiver/gnomod.toml new file mode 100644 index 00000000..3fbcb7b8 --- /dev/null +++ b/gno.land/r/onbloc/ibc/testing/mock/receiver/gnomod.toml @@ -0,0 +1,2 @@ +module = "gno.land/r/onbloc/ibc/testing/mock/receiver" +gno = "0.9" diff --git a/gno.land/r/onbloc/ibc/scenario/ignore/testing/mock/mock.gno b/gno.land/r/onbloc/ibc/testing/mock/receiver/receiver.gno similarity index 99% rename from gno.land/r/onbloc/ibc/scenario/ignore/testing/mock/mock.gno rename to gno.land/r/onbloc/ibc/testing/mock/receiver/receiver.gno index 1e588d59..3cf64717 100644 --- a/gno.land/r/onbloc/ibc/scenario/ignore/testing/mock/mock.gno +++ b/gno.land/r/onbloc/ibc/testing/mock/receiver/receiver.gno @@ -1,4 +1,4 @@ -package mock +package receiver import ( "errors"