-
Notifications
You must be signed in to change notification settings - Fork 33
Utility Relay Protocol
The Relay Protocol is a fundamental sequence that makes up the building blocks of Pocket Network's Utility.
In Pocket Network, a Relay
is a Read / Write API request operation to a 3rd party RelayChain
.
The Relay Protocol is the servicing lifecycle that poises staked Servicers to be able to complete Relays on behalf of the network.
The foundational lifecycle of the Relay Protocol is:
- Validate the inbound
Relay
- Store / persist the
Relay
- Execute the Relay against the
RelayChain
sequenceDiagram
title Steps 1 to 3
autonumber
actor App
actor Client
actor Servicer
participant Internal State
participant Internal Storage
participant External Relay Chain
App->>Client: Provision(AppAuthToken)
loop Repeats Throughout Session Duration
Client->>Client: Sign(Relay)
Client->>Servicer: Send(Relay)
Servicer->>Internal State: Validate(Relay)
Internal State->>Servicer: IsValid(Relay)
Servicer->>Internal Storage: IfValid(Relay) -> Persist(Relay)
Servicer->>External Relay Chain: Execute(Relay, RelayChainURL)
External Relay Chain->>Servicer: RelayResponse = GetResponse(RelayChain)
Servicer->>Servicer: Sign(RelayResponse)
Servicer ->> Client: Send(RelayResponse)
end
- Wait for
Session
end / secret key to be revealed - Collect Volume Applicable Relays (based on secret key) from storage
- Report Volume Applicable Relays to the assigned
Fisherman
sequenceDiagram
title Steps 4-6
autonumber
actor Servicer
participant Internal State
participant Internal Storage
actor Fisherman
loop Repeats Every Session End
Servicer->>Internal State: GetSecretKey(sessionHeader)
Internal State->>Servicer: HashCollision = SecretKey(govParams)
Servicer->>Internal Storage: RelaysThatEndWith(HashCollision)
Internal Storage->>Servicer: VolumeApplicableRelays
Servicer->>Fisherman: Send(VolumeApplicableRelays)
end
A multi-step validation process to validate a submitted relay by a client before servicing
- Validate payload, look for empty or 'bad' request data
- Validate the metadata, look for empty or 'bad' metadata
- Ensure the
RelayChain
is supported locally (in the servicer's configuration files) - Ensure session block height is current
- Get the
sessionContext
to access values and parameters from world state at that height - Get the application object from the
request.AAT()
(usingsessionContext
) - Get session node count from that session height (using
sessionContext
) - Get max relays per session for the application (using
sessionContext
) - Ensure not over serviced (if max relays is exceeded, not compensated for further work)
- Generate the session from seed data (see Session Protocol)
- Validate self against the session (is node within session)
graph TD
A[Relay.Validate] -->B
B[HasValidPayload] -->|Yes| C
B -->|No| Z
C[HasValidMeta] -->|Yes| D
C -->|No| Z
D[RelayChainIsSupported]-->|Yes| E
D -->|No| Z
E[IsValidSessionHeight]-->|Yes| F
E -->|No| Z
F[IsAppOverServiced]-->|No| G
F -->|Yes| Z
G[IsValidSession]-->|Yes| X
G -->|No| Z
X[Relay Is Valid]
Z[Reject Invalid Relay]
Store a submitted Relay
by a client for volume tracking
- Marshal
Relay
object into codecBytes - Calculate the
hashOf(codecBytes)
- Persist
Relay
object, indexing under session
graph TD
A[Relay.Store] -->|Encode `Relay` object| B
B[RelaycodecBytes] -->|Calculate Hash for Volume Tracking| C
C[RelaycodecBytes.Hash] -->|Add Hash to `Relay` and Persist| D
D[Relay.Persist] --> |Indexing Under Session| E
E[Key:SessionKey Val: Relays.AddNew]
Execute a submitted Relay
against the RelayChain
by a client after validation
- Retrieve the
RelayChain
url from the servicer configuration files - Execute http request with the
Relay Payload
- Format and digitally sign the response using the servicer's private key
- Send back to client
It's important to note, the secret key isn't revealed by the network until the session is over to prevent volume based bias. The secret key is usually a pseudorandom selection using the block hash as a seed. See the Session Protocol for more details.
- Pull all
Relays
whose hash collides with the revealed secret key
SELECT * FROM relay WHERE HashOf(relay) END WITH hashEndWith AND session=relay.Session
- This function also signifies deleting the non-volume-applicable
Relays
- All volume applicable relays need to be sent to the assigned trusted
Fisherman
(selected by the Session Protocol) for a proper verification of the volume completed. - Send
volumeRelays
tofishermanServiceUrl
through http.
graph TD
A[Relay.Execute] -->|Lookup Relay.RelayChain URL|B
B[Chains.JSON -> RelayChainURL] -->|Execute Http Request| C
C[RelayChain] -->|Return Response| D
D[RelayResponse.Sign] --> |Send|E
E[Requester]
An alternative design is a 2-step, claim-proof lifecycle where the individual servicers build a Merkle sum index tree from all the relays, submits a root and subsequent Merkle proof to the network via a commit+reveal schema.
- Pros: Can report volume metrics directly to the chain in a trustless fashion
- Cons: Large chain bloat, non-trivial compute requirement for creation of claim/proof transactions and trees, non-trivial compute requirement to process claim / proofs during ApplyBlock()
This algorithm is not yet documented anywhere, so the following links can act as a reference in the interim.
Documentation:
- Pocket docs: https://docs.pokt.network/home/v0/protocol/servicing#claim-proof-lifecycle
- Twitter Thread: https://twitter.com/o_rourke/status/1263847357122326530
- Plasma core Merkle Sum Tree: https://plasma-core.readthedocs.io/en/latest/specs/sum-tree.html
V0 Source Code References:
- Merkle: pocketcore/types/merkle.go
- Claim: pocketcore/keeper/claim.go
- Proof: pocketcore/keeper/proof.go
Contents
- Home
- Persistence
- Changelog
-
Persistence
- Indexer
- Rpc
- Runtime
- State_Machine
-
Guides
- Roadmap
-
Guides
- Learning
- Guides
-
Guides
- Contributing
- Devlog
-
Guides
- Dependencies
-
Guides
- Releases
- Guides
- P2P
-
Shared
- Crypto
- Shared
-
Shared
- Modules
-
Build
- Config
- Consensus
-
Guides
- Telemetry
- Utility
- Logger