Skip to content

Commit

Permalink
Merge branch 'feat/integrate-bg-router' (early part) into chore/intro…
Browse files Browse the repository at this point in the history
…duce-submodule

* 'feat/integrate-bg-router' (early part): (21 commits)
  test: fix raintree message target test
  [P2P] refactor: unicast router (#844)
  chore: add TECHDEBT comment
  Update E2E_FEATURE_LIST.md
  Update vault_test.go (#862)
  chore: return early
  chore: improve debug logging
  chore: improve comments
  chore: improve variable naming
  fix: `p2pModule#Send()` routing logic
  fix: interim background router bootstrapping
  chore: router logging improvements
  fix: return error
  chore: cleanup unused garbage
  chore: add missing godoc comments
  chore: add submodule TECHDEBT comments
  chore: comment cleanup
  chore: cleanup unused test utils
  [IBC] Create initial IBC module (#842)
  [Persistence] Adds TreeStore logger (#852)
  ...
  • Loading branch information
bryanchriswhite committed Jun 29, 2023
2 parents fcb480e + fe42ab3 commit 90fe9c4
Show file tree
Hide file tree
Showing 54 changed files with 1,446 additions and 217 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@ test_p2p_raintree: ## Run all p2p raintree related tests
test_p2p_raintree_addrbook: ## Run all p2p raintree addr book related tests
go test ${VERBOSE_TEST} -count=1 -tags=test -run RainTreeAddrBook -count=1 ./p2p/...

.PHONY: test_ibc
test_ibc: ## Run all go unit tests in the IBC module
go test ${VERBOSE_TEST} -count=1 -tags=test -p=1 ./ibc/...

# TIP: For benchmarks, consider appending `-run=^#` to avoid running unit tests in the same package

.PHONY: benchmark_persistence_state_hash
Expand Down
2 changes: 1 addition & 1 deletion app/client/keybase/hashicorp/vault_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestMain(m *testing.M) {
// pulls an image, creates a container based on it and runs it
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
Repository: "vault",
Tag: "latest",
Tag: "1.13.3",
Env: []string{
"VAULT_DEV_ROOT_TOKEN_ID=dev-only-token",
"VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200",
Expand Down
3 changes: 3 additions & 0 deletions build/config/config.validator1.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,8 @@
"servicer": {
"enabled": true,
"chains": ["0001"]
},
"ibc": {
"enabled": true
}
}
3 changes: 3 additions & 0 deletions build/config/config.validator2.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@
"port": "50832",
"timeout": 30000,
"use_cors": false
},
"ibc": {
"enabled": true
}
}
3 changes: 3 additions & 0 deletions build/config/config.validator3.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@
"port": "50832",
"timeout": 30000,
"use_cors": false
},
"ibc": {
"enabled": true
}
}
3 changes: 3 additions & 0 deletions build/config/config.validator4.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@
"port": "50832",
"timeout": 30000,
"use_cors": false
},
"ibc": {
"enabled": true
}
}
10 changes: 4 additions & 6 deletions consensus/e2e_tests/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/pokt-network/pocket/consensus"
typesCons "github.com/pokt-network/pocket/consensus/types"
"github.com/pokt-network/pocket/internal/testutil"
ibcUtils "github.com/pokt-network/pocket/internal/testutil/ibc"
persistenceMocks "github.com/pokt-network/pocket/persistence/types/mocks"
"github.com/pokt-network/pocket/runtime"
"github.com/pokt-network/pocket/runtime/configs"
Expand All @@ -24,7 +25,6 @@ import (
"github.com/pokt-network/pocket/shared"
"github.com/pokt-network/pocket/shared/codec"
coreTypes "github.com/pokt-network/pocket/shared/core/types"
"github.com/pokt-network/pocket/shared/crypto"
cryptoPocket "github.com/pokt-network/pocket/shared/crypto"
"github.com/pokt-network/pocket/shared/messaging"
"github.com/pokt-network/pocket/shared/modules"
Expand Down Expand Up @@ -122,13 +122,15 @@ func CreateTestConsensusPocketNode(
telemetryMock := baseTelemetryMock(t, eventsChannel)
loggerMock := baseLoggerMock(t, eventsChannel)
rpcMock := baseRpcMock(t, eventsChannel)
ibcMock := ibcUtils.IbcMockWithHost(t, eventsChannel)

for _, module := range []modules.Module{
p2pMock,
utilityMock,
telemetryMock,
loggerMock,
rpcMock,
ibcMock,
} {
bus.RegisterModule(module)
}
Expand Down Expand Up @@ -669,7 +671,6 @@ func waitForProposalMsgs(
maxWaitTime time.Duration,
failOnExtraMessages bool,
) ([]*anypb.Any, error) {

proposalMsgs, err := WaitForNetworkConsensusEvents(t, clck, eventsChannel, typesCons.HotstuffStep(step), consensus.Propose, numExpectedMsgs, maxWaitTime, failOnExtraMessages)
if err != nil {
return nil, err
Expand Down Expand Up @@ -751,7 +752,6 @@ func waitForNodeToRequestMissingBlock(
startingHeight uint64,
targetHeight uint64,
) (*anypb.Any, error) {

return &anypb.Any{}, nil
}

Expand All @@ -765,7 +765,6 @@ func waitForNodeToReceiveMissingBlock(
allNodes IdToNodeMapping,
blockReq *anypb.Any,
) (*anypb.Any, error) {

return &anypb.Any{}, nil
}

Expand All @@ -779,11 +778,10 @@ func waitForNodeToCatchUp(
blockResponse *anypb.Any,
targetHeight uint64,
) error {

return nil
}

func generatePlaceholderBlock(height uint64, leaderAddrr crypto.Address) *coreTypes.Block {
func generatePlaceholderBlock(height uint64, leaderAddrr cryptoPocket.Address) *coreTypes.Block {
blockHeader := &coreTypes.BlockHeader{
Height: height,
StateHash: stateHash,
Expand Down
111 changes: 111 additions & 0 deletions ibc/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# IBC <!-- omit in toc -->

- [Definitions](#definitions)
- ["host"](#host)
- ["light client"](#light-client)
- [Overview](#overview)
- [IBC Module](#ibc-module)
- [Node Configuration](#node-configuration)
- [Persistence](#persistence)
- [Components](#components)
- [ICS-24 Host Requirements](#ics-24-host-requirements)

## Definitions

### "host"

An IBC host refers to the node (host machine) that is running the IBC module. Relayers will interact with the hosts on each chain in order to call any IBC related functions. The IBC host is responsible for storing and interfacing with the IBC state and handling any IBC related transactions.

### "light client"

An IBC light client refers to a consensus state verification algorithm. This is different from the traditional meaning of the term. An IBC light client will be only used for state verification and will lack many of the other features commonly found in traditional light clients.

## Overview

![IBC High Level](./high-level-ibc.png)

Inter-Blockchain Communication (IBC) is a protocol that enables trustless communication between two chains. It allows these chains to interact by relaying IBC packets. The process involves two IBC-enabled chains, referred to as **chain A** and **chain B**, each running a light client for the other chain on their network.

To transfer native tokens from **chain A** to **chain B**, certain prerequisites must be met. First, a connection between the two chains must be established. Then, a channel and port need to be opened on this connection. Additionally, a light client for the opposing chain should be set up on both ends of the connection. Finally, a relayer is required to facilitate the actual transfer of the packet.

Once these components are in place, **chain A** can commit an IBC packet to its state, which contains transaction information. It also generates a proof that specifies the inclusion of the packet in the state at a particular height. The relayer submits this proof to **chain B**, where it is verified. If the proof is valid, **chain B** can respond accordingly, such as by sending an IBC token from **chain A** to the designated address on **chain B**.

## IBC Module

Pocket's IBC module is split into numerous components detailed below. The overall module layout is as follows:

**Note:** Not all of the different ICS components have been fully implemented yet, this is a work in progress.

```mermaid
flowchart TB
subgraph IBC[IBC Module]
subgraph 23[ICS-23]
VC[Vector Commitments]
end
subgraph 24[ICS-24]
HR[Host Requirements]
end
subgraph I[IBC Interface]
IF[ICS-25 Handler Interface]
IR[ICS-26 Routing Module]
end
end
subgraph 2[ICS-02]
CL[Client Semantics]
end
subgraph 3[ICS-03]
CO[Connection Semantics]
end
subgraph 5[ICS-05]
PA[Port Allocation]
end
subgraph 4[ICS-04]
CP[Channel & Packet Semantics]
end
subgraph 20[ICS-20]
FT[Fungible Token Transfer]
end
IBC ---> 2
IBC ---> 3
IBC ---> 5
IBC ---> 4
IBC ---> 20
```

### Node Configuration

Part of the node configurations relating to the IBC module is as follows:

```json
"ibc": {
"enabled": bool,
}
```

If a node enables the IBC module, and is a validator, then the IBC module will automatically create an IBC host on startup. As the host defines the connections, channels and ports - which must stay persistent, the node should be a validator with little risk of suddenly closing any of these while open. Any tokens transferred over a connection/channel/port are unique to that combination they can only be returned over the same combination.

**If the channel is to close without warning then tokens will be unable to be returned to their source. It is for this reason that only validators are able to become IBC hosts.**

INVESTIGATE(M7): Look into on-chain POKT slashing/incentive conditions based on the QoS of an IBC host.

_Note_: Connections, Channels and Ports in IBC are not the same as networking connections, channels and ports. They are stored in the chain state and are used by relayers to signify where each IBC packet should go when being relayed. When closing a channel the IBC host must submit to the state a `ChanCloseInit` IBC packet. If this happens without warning, the funds transferred on this channel will become unrecoverable.

### Persistence

[ICS24][ics24] defines the IBC stores and these must be a part of the Pocket networks consensus state. As such the `ibcTree` is defined as one of the state trees used to generate the root hash. This tree contains the relevant information the hosts/relayers need to be able to use IBC, in accordance with ICS-24 and the other ICS components.

TODO([#854](https://github.com/pokt-network/pocket/issues/854)): Add a local cache for changes to the state for use in the event of the node crashing.

## Components

The [IBC specification][ibc-spec] details numerous Interchain Standards (ICSs) that together form the IBC protocol. The following gives an overview of the different components implemented in Pocket's IBC module.

### ICS-24 Host Requirements

[ICS-24][ics24] defines the requirements for a host chain to be IBC compatible. This includes the definition of a store system to hold IBC related data in a provable (and also a private) fashion. This implementation uses the [SMT][smt] rather than the IAVL tree used by `cosmos-sdk` for its provable stores. ICS-24 also defines the Event Logging system that is used to store and query IBC related events for the relayers to read packet data and timeouts, as only the proofs of these are stored in the chain state.

See: [ICS-24](./ics24.md) for more details on the specifics of the ICS-24 implementation for Pocket.

[ibc-spec]: https://github.com/cosmos/ibc
[ics24]: https://github.com/cosmos/ibc/blob/main/spec/core/ics-024-host-requirements/README.md
[smt]: https://github.com/pokt-network/smt
Binary file added ibc/docs/high-level-ibc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions ibc/docs/ics24.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# ICS-24 Host Requirements <!-- omit in toc -->

- [Overview](#overview)
- [Implementation](#implementation)
- [Paths and Identifiers](#paths-and-identifiers)
- [Timestamps](#timestamps)

## Overview

[ICS-24][ics24] details the requirements of the host chain, in order for it to be compatible with IBC. A host is defined as a node on a chain that runs the IBC software. A host has the ability to create connections with counterparty chains, open channels, and ports as well as commit proofs to the consensus state of its own chain for the relayer to submit to another chain. The host is responsible to managing and creating clients and all other aspects of the IBC module.

As token transfers as defined in [ICS-20][ics20] work on a lock and mint pattern, any tokens sent from **chain A** to **chain B** will have a denomination unique to the connection/channel/port combination that the packet was sent over. This means that if a host where to shutdown a connection or channel without warning any tokens yet to be returned to the host chain would be lost. For this reason, only validator nodes are able to become hosts, as they provide the most reliability out of the different node types.

## Implementation

**Note**: The ICS-24 implementation is still a work in progress and is not yet fully implemented.

ICS-24 has numerous sub components that must be implemented in order for the host to be fully functional. These range from type definitions for identifiers, paths and stores as well as the methods to interact with them. Alongside these ICS-24 also defines the Event Logging system which is used to store the packet data and timeouts for the relayers to read, as only the `CommitmentProof` objects are committed to the chain state. In addition to these numerous other features are part of ICS-24 that are closely linked to other ICS components such as consensus state introspection and client state validation.

### Paths and Identifiers

Paths are defined as bytestrings that are used to access the elements in the different stores. They are built with the function `ApplyPrefix()` which takes a store key as a prefix and a path string and will return the key to access an element in the specific store. The logic for paths can be found in [host/keys.go](../host/keys.go) and [host/prefix.go](../host/prefix.go)

Identifiers are bytestrings constrained to specific characters and lengths depending on their usages. They are used to identify: channels, clients, connections and ports. Although the minimum length of the identifiers is much less we use a minimum length of 32 bytes and a maximum length that varies depending on the use case to randomly generate identifiers. This allows for an extremely low chance of collision between identifiers. Identifiers have no significance beyond their use to store different elements in the IBC stores and as such there is no need for non-random identifiers. The logic for identifiers can be found in [host/identifiers.go](../host/identifiers.go).

### Timestamps

The `GetTimestamp()` function returns the current unix timestamp of the host machine and is used to calculate timeout periods for packets

[ics24]: https://github.com/cosmos/ibc/blob/main/spec/core/ics-024-host-requirements/README.md
[ics20]: https://github.com/cosmos/ibc/blob/main/spec/app/ics-020-fungible-token-transfer/README.md
[smt]: https://github.com/pokt-network/smt
18 changes: 18 additions & 0 deletions ibc/host.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ibc

import (
"time"

"github.com/pokt-network/pocket/shared/modules"
)

var _ modules.IBCHost = &host{}

type host struct {
logger *modules.Logger
}

// GetTimestamp returns the current unix timestamp
func (h *host) GetTimestamp() uint64 {
return uint64(time.Now().Unix())
}
Loading

0 comments on commit 90fe9c4

Please sign in to comment.