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
|
[[DLTs]] | Terminology
|
||||||
[[Finality]] | Terminology
|
[[Finality]] | Terminology
|
||||||
[[Flation]] | Terminology: Inflation, Deflation, Coins, Tokens, and Prices
|
[[Flation]] | Terminology: Inflation, Deflation, Coins, Tokens, and Prices
|
||||||
|
[[GRIDS]] | Gajumaru Remote Instruction Dispatch Schema
|
||||||
[[Install Erlang and zx]] | Tech Support
|
[[Install Erlang and zx]] | Tech Support
|
||||||
[[Leader Selection]] | Terminology
|
[[Leader Selection]] | Terminology
|
||||||
[[Mempool]] | Terminology
|
[[Mempool]] | Terminology
|
||||||
@@ -26,7 +27,7 @@ Title | Brief Description
|
|||||||
[[Smart Contracts]] | Terminology
|
[[Smart Contracts]] | Terminology
|
||||||
[[Sophia]] | Introduction to Sophia, the Gajumaru smart contract language
|
[[Sophia]] | Introduction to Sophia, the Gajumaru smart contract language
|
||||||
[[Sophia FAQ]] | what it says
|
[[Sophia FAQ]] | what it says
|
||||||
[[State Channels]] | Overview and characteristics
|
[[State Channels]] | Overview and characteristics
|
||||||
[[Testnet Node Setup]] | Tech support
|
[[Testnet Node Setup]] | Tech support
|
||||||
[[Transaction] | Terminology
|
[[Transaction] | Terminology
|
||||||
|
|
||||||
|
|||||||
@@ -254,4 +254,6 @@ compile_spec(TokenSpecs) ->
|
|||||||
end.
|
end.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# How does sophia compilation work
|
# How does sophia compilation work
|
||||||
|
|||||||
Reference in New Issue
Block a user