public wiki grids page
+272
@@ -0,0 +1,272 @@
|
||||
|
||||
# GRIDS: Gajumaru Remote Instruction Dispatch System v1
|
||||
|
||||
-------------------------|-------------------------------------------
|
||||
Document Created | 2025-01-17
|
||||
Document Last Modified | 2025-12-08
|
||||
Document Author | Craig Everett `<craigeverett@qpq.swiss>`
|
||||
Document Version | 3: For Implementation
|
||||
Wiki Page Created | 2026-05-02
|
||||
Wiki Page Last Modified | 2026-05-02
|
||||
Wiki Page Author | Peter Harpending `<peterharpending@qpq.swiss>`
|
||||
Notes | Copied from random PDF I found on my computer written by Craig, dated 2025-01-17.
|
||||
-------------------------|-------------------------------------------
|
||||
|
||||
The GRIDS protocol defines methods for encoding three basic actions within the
|
||||
Gajumaru ecosystem:
|
||||
|
||||
1. A method for encoding "spend" transactions in a URL where the host section
|
||||
indicates a specific endpoint node to use, the required network ID being
|
||||
then queried from the endpoint.
|
||||
2. A method for encoding "transfer" transactions in a URL where the host
|
||||
section indicates a network to use but leaves resolving an endpoint node up
|
||||
to the client.
|
||||
3. A method for performing digital "dead drop" signatures, queuing signature
|
||||
requests on a server, retrieving them with a client, and returning the
|
||||
resulting signed output to the server.
|
||||
|
||||
|
||||
## The Problem
|
||||
|
||||
In computing there is a strong tradeoff between usability and security. In the
|
||||
cryptocurrency world this is compounded by the inherent complexity of the
|
||||
systems involved. This has resulted in a common pattern of developers coding
|
||||
wallet features directly into the local execution environments of the
|
||||
applications they wish to integrate with a cryptocurrency system (typically a
|
||||
blockchain).
|
||||
|
||||
For example, it is common for games based around on-chain tokens to integrate
|
||||
wallet features directly into the game client itself. This prevents the user
|
||||
from having to leave the game, open another application (their wallet), sign a
|
||||
transaction, and then return to the game.
|
||||
|
||||
As another example, it is overwhelmingly common for developers to write
|
||||
wallets as browser plugins that interact directly with in-page applications
|
||||
running in the same browser.
|
||||
|
||||
In both cases the incentives for bad actors to compromise the execution
|
||||
environment itself in order to capture private key data or seed phrases is
|
||||
overwhelming. Separation of signature and app execution context is needed.
|
||||
Separating the execution context requires a way for apps requesting signatures
|
||||
and apps capable of providing signatures to communicate not only across
|
||||
execution environments on a single system, but also across completely separate
|
||||
systems.
|
||||
|
||||
GRIDS defines a way to to combine communication of limited, known transaction
|
||||
types (such as simple spends) with a way to convey arbitrarily complex
|
||||
transaction data that may require out-of-band communication with a signature
|
||||
client.
|
||||
|
||||
## The Schema
|
||||
|
||||
The GRIDS schema is very similar to HTTP/HTTPS, and even translates directly
|
||||
to an HTTP request URL in the case of a dead-drop instruction.
|
||||
|
||||
The basic schema is:
|
||||
|
||||
```
|
||||
[grid(s)]://[host]/[version]/[instruction]/[path](?a=[amount]&p=[payload])
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
- The schema identifier is either `grids` or `grid`. If the instruction is a
|
||||
dead-drop signature then the schema may be `grid` to indicate that the
|
||||
initial pick up request must be made over HTTP rather than HTTPS. If the
|
||||
instruction is not a dead-drop, then there is no difference between the two.
|
||||
- The `host` element is interpreted differently based on instruction type:
|
||||
- For `s` (short for "spend") it is the network ID where the spend is to
|
||||
take place.
|
||||
- For `t` (short for "transfer") it is a `host:port` location of a node
|
||||
where the client can retrieve the network ID.
|
||||
- For `d` (short for "dead-drop") it is a `host:port` location of a service
|
||||
where a message to be signed is awaiting pickup.
|
||||
- The `version` element is the protocol version.
|
||||
- As mentioned above, the `instruction` element is one of `s` (for "spend"),
|
||||
`t` (for "transfer"—same as spend but with different host semantics) or `d`
|
||||
(for "dead-drop").
|
||||
- In the case of dead-drops, the `path` element is the HTTP path to the pickup
|
||||
location. In the case of spends/transfers it is the address of the party to
|
||||
be paid, with (optional) amount and payload details packed into query args
|
||||
of the forms
|
||||
|
||||
- `a=[amount]` denominated in pucks, represented in the numerals `[0-9]`
|
||||
- `p=[payload]` represented as URL-encoded binary data
|
||||
|
||||
## The simple case: SpendTX
|
||||
|
||||
Spends are simple on-chain transactions that transfer coins (Gajus/Pucks) from
|
||||
one account to another.
|
||||
|
||||
Defined as a record, the inner data in a SpendTX looks like this:
|
||||
|
||||
```erlang
|
||||
-record(spend_tx,
|
||||
{sender_id :: string(),
|
||||
recipient_id :: string(),
|
||||
amount :: non_neg_integer(),
|
||||
gas_price :: pos_integer(),
|
||||
gas :: pos_integer(),
|
||||
ttl :: pos_integer(),
|
||||
nonce :: pos_integer(),
|
||||
payload :: binary()}).
|
||||
```
|
||||
|
||||
All elements are required with the exception of the `payload`, which can be
|
||||
empty. The payload is used to tag spend transactions with meaningful data such
|
||||
as text indicating what a transaction was for or an invoice number useful for
|
||||
tracking within an accounting system. Elements such as the `gas_price`, `gas`,
|
||||
`ttl` and `nonce` are all elements that a client wallet is expected to
|
||||
populate on its own.
|
||||
|
||||
The external data required for a SpendTX is the network ID of the specific
|
||||
chain that the spend transaction is intended for. The network ID is part of
|
||||
the external encoding of the TX, the encoded representation of the transaction
|
||||
(including the network ID) is what the client ultimately signs. The
|
||||
combination of the nonce and network ID prevents TXs from being replayed on
|
||||
the same network or replayed across different networks.
|
||||
|
||||
The information required from a party requesting an on-chain payment is
|
||||
therefore reduced to:
|
||||
|
||||
1. The account to be paid
|
||||
2. The amount
|
||||
3. Any payload desired (an invoice number, for example)
|
||||
4. The network ID or a host address of a node from which the network ID can be
|
||||
obtained.
|
||||
|
||||
This data is encoded in a GRIDS URL as noted above.
|
||||
|
||||
GRIDS URLs should be provided to users as both plain text and a QR code to
|
||||
make it easy to verify their content as well as make it possible to easily use
|
||||
both desktop (copy-paste) and mobile (camera input) wallet apps.
|
||||
|
||||
### Example Spends
|
||||
|
||||
Let's say a point-of-sale system at shop needs to charge a customer 25 Gajus.
|
||||
The POS system knows its own account address for the register, knows the
|
||||
invoice number, knows the amount to charge, and knows that it is operating on
|
||||
the `groot.mainnet` network, but does not know the
|
||||
customer's account number.
|
||||
|
||||
Assume the following payment information:
|
||||
|
||||
- Store account: `ak_srFAGY9Dq6p8LVoPSQ8o86s6EFAqWsXHKLDvpzPFcZ8txtR6U`
|
||||
- Amount: 25 Gajus
|
||||
- Invoice number: `20250117-0001`
|
||||
|
||||
The POS system can generate a GRIDS request encoded as:
|
||||
|
||||
```
|
||||
grids://groot.mainnet/1/s/ak_srFAGY9Dq6p8LVoPSQ8o86s6EFAqWsXHKLDvpzPFcZ8txtR6U?a=25000000000000000000&p=20250117-0001
|
||||
```
|
||||
|
||||
Alternately, if the POS system is operating on an associate chain that isn't as
|
||||
common, or is running its own backend node for efficiency purposes, it could
|
||||
request a "transfer" instruction, specifying its
|
||||
node's public address and the wallet can retrieve the network ID from there:
|
||||
|
||||
```
|
||||
grids://some.shop:4321/1/t/ak_srFAGY9Dq6p8LVoPSQ8o86s6EFAqWsXHKLDvpzPFcZ8txtR6U?a=25000000000000000000&p=20250117-0001
|
||||
```
|
||||
|
||||
If the node running at `some.shop:4321` is a part of `groot.mainnet`, then
|
||||
these two request URLs are effectively identical.
|
||||
|
||||
## Dead-Drops
|
||||
|
||||
The most flexible case for GRIDS is the dead-drop. Using this technique
|
||||
anything can be communicated to a client, signed, and returned. Dead-drops can
|
||||
be used for signatures of contract calls, login messages, or any other kind of
|
||||
message signature one might require.
|
||||
|
||||
As mentioned above, dead-drop GRIDS URLs are converted to HTTP URLs by
|
||||
stripping off the GRIDS version and instruction tags and reassembling the
|
||||
request as an HTTP or HTTPS request.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
grids://foo.com/1/d/some_random_path -> https://foo.com/some_random_path
|
||||
grid://foo.com/1/d/some_random_path -> http://foo.com/some_random_path
|
||||
```
|
||||
|
||||
After that conversion takes place, the client makes a GET request to the HTTP
|
||||
URL indicated. The response from the server is a JSON object containing the
|
||||
unsigned data and some metadata that tells the client what kind of message is
|
||||
being signed so that the client can select the correct signature method.
|
||||
|
||||
After signing, the JSON object is updated with the signed data and the public
|
||||
half of the signing key. The client then submits in a POST request the updated
|
||||
JSON object back to the original endpoint from which the unsigned data was
|
||||
retrieved.
|
||||
|
||||
### Signature Request Messages (initial GET)
|
||||
|
||||
The response to the initial GET request takes the form of a JSON object with this shape:
|
||||
|
||||
```json
|
||||
{"grids" : 1,
|
||||
"chain" : "gajumaru",
|
||||
"network_id" : "groot.mainnet",
|
||||
"type" : "tx",
|
||||
"public_id" : "ak_2SLsxkPavd1oDwUgCyZkMoQJJvMkUWymg1BEK7egx5rVU8xanV",
|
||||
"payload" : "Any data here"}
|
||||
```
|
||||
|
||||
- The `"grids"` version will always match the version encoded in the request URL.
|
||||
- The `"chain"` element exists in case other projects want to adopt the GRIDS
|
||||
protocol, in which case the protocol rules of the specific chain family will
|
||||
dictate things like serialization details.
|
||||
- The `"network_id"` is necessary for the client (and end-user) to verify that
|
||||
activity is occurring where expected and binds the resulting signature to
|
||||
that specific network.
|
||||
- The `"type"` may be `"message"`, `"tx"` or `"ack"`. A `"message"` signature
|
||||
is used either for verifiable messages or login schemes. An `"ack"` is an
|
||||
optional response to a `"tx"` or `"message"` response POST.
|
||||
- The `"public_id"` can either be a public key (on-chain account) or the
|
||||
**boolean** `false` (note absence of quotes).
|
||||
|
||||
- If the `public_id` is `false`, then it is up to the client to pick a key to
|
||||
use (and then populate this field).
|
||||
- If an ID is specified, then the client should select that account or fail if it is not available.
|
||||
|
||||
- The `"payload"` is the data to be signed. In the case of a
|
||||
`"tx"` request (a contract call, for example), this data
|
||||
will be transaction data encoded according to the Gajumaru
|
||||
protocol's rules. Any Gajumaru signature routine will
|
||||
understand how to interpret and handle this data. In the
|
||||
case of a `"message"` request, this will typically be a
|
||||
simple string in plain text that the client interprets as a
|
||||
binary string, appends the prefix (Erlang binary notation)
|
||||
`<<"Gajumaru Signed Message:\n">>`, and then signs.
|
||||
Prefixing message request payloads with this string prevents
|
||||
attackers from disguising transaction signature requests as
|
||||
text message signatures.
|
||||
|
||||
### Signed Data Messages (subsequent POST)
|
||||
|
||||
After the client signs the payload, it will populate the
|
||||
`"public_id"` element (if it was `false` previously) and add
|
||||
`"signature"` element with the requested signature. The
|
||||
resulting object that must be POSTed back to the origin is
|
||||
therefore:
|
||||
|
||||
```json
|
||||
{"grids" : 1,
|
||||
"chain" : "gajumaru",
|
||||
"network_id" : "groot.mainnet",
|
||||
"type" : "tx",
|
||||
"public_id" : "ak_2SLsxkPavd1oDwUgCyZkMoQJJvMkUWymg1BEK7egx5rVU8xanV",
|
||||
"payload" : "Any data here",
|
||||
"signature" : "XiuCkEOHINkQN83QUxmIAfmiiRN2XflktnNMtdZDzgW0TQK/YQaurQjfL3R5eoXJvCuUZRgPpKfCvtsXbphDCQ=="}
|
||||
```
|
||||
|
||||
The server (or any other observer of this message) now has
|
||||
enough information to establish for certain whether whoever
|
||||
signed this message has control of the private key that
|
||||
corresponds to the public key indicated in the message.
|
||||
|
||||
Signing of randomized and timestamped messages can be used to
|
||||
implement First-Party Single Sign-On (1pSSO) schemes without
|
||||
any requirement that the server side maintain private data.
|
||||
+2
-1
@@ -13,6 +13,7 @@ Title | Brief Description
|
||||
[[DLTs]] | Terminology
|
||||
[[Finality]] | Terminology
|
||||
[[Flation]] | Terminology: Inflation, Deflation, Coins, Tokens, and Prices
|
||||
[[GRIDS]] | Gajumaru Remote Instruction Dispatch Schema
|
||||
[[Install Erlang and zx]] | Tech Support
|
||||
[[Leader Selection]] | Terminology
|
||||
[[Mempool]] | Terminology
|
||||
@@ -26,7 +27,7 @@ Title | Brief Description
|
||||
[[Smart Contracts]] | Terminology
|
||||
[[Sophia]] | Introduction to Sophia, the Gajumaru smart contract language
|
||||
[[Sophia FAQ]] | what it says
|
||||
[[State Channels]] | Overview and characteristics
|
||||
[[State Channels]] | Overview and characteristics
|
||||
[[Testnet Node Setup]] | Tech support
|
||||
[[Transaction] | Terminology
|
||||
|
||||
|
||||
@@ -254,4 +254,6 @@ compile_spec(TokenSpecs) ->
|
||||
end.
|
||||
```
|
||||
|
||||
|
||||
|
||||
# How does sophia compilation work
|
||||
|
||||
Reference in New Issue
Block a user