public wiki grids page

Peter Harpending
2026-05-02 13:43:57 -07:00
parent cf096bb4ed
commit 0616c91ba0
3 changed files with 276 additions and 1 deletions
+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
+2
@@ -254,4 +254,6 @@ compile_spec(TokenSpecs) ->
end.
```
# How does sophia compilation work