Skip to content

Commit 628933c

Browse files
authored
Merge branch 'master' into xls-41d
2 parents 3a6aa05 + b6afb82 commit 628933c

File tree

4 files changed

+315
-1
lines changed

4 files changed

+315
-1
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
uses: actions/configure-pages@v5
4848

4949
- name: Upload artifact
50-
uses: actions/upload-pages-artifact@v3
50+
uses: actions/upload-pages-artifact@v4
5151
with:
5252
path: "site/_site"
5353

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<pre>
2+
xls: 6
3+
title: Standard for Visual Account Icons
4+
description: A standard for visually distinguishing XRPL accounts by generating unique icons for each account, regardless of address format.
5+
author: Richard Holland (RichardAH)
6+
discussion-from: https://github.com/XRPLF/XRPL-Standards/discussions/24
7+
status: Final
8+
category: Community
9+
created: 2019-09-22
10+
</pre>
11+
12+
Following from [XLS-5d](https://github.com/XRPLF/XLS-0005-standards-for-addressing), it has become necessary to provide XRPL users a way to identify their XRPL account, which effectively now has two different identifiers: an 'r-address' and an 'X-address'.
13+
14+
To solve this problem XLS-6d provides for a standard way to visually identify accounts irrespective of which addressing system is used by the rest of the user interface.
15+
16+
For a user account take the X-address of the account without destination tag and feed it into hashicon https://www.npmjs.com/package/hashicon
17+
18+
For an exchange, take the X-address of the account with the destination tag and feed it into hashicon.
19+
20+
It's recommended that these icons are displayed alongside addresses to help reduce user confusion. See examples in Figures 1 and 2.
21+
22+
![image](https://user-images.githubusercontent.com/19866478/65387069-ba273a80-dd86-11e9-8680-34488e15401d.png)
23+
Figure 1
24+
25+
![image](https://user-images.githubusercontent.com/19866478/65387078-dc20bd00-dd86-11e9-90af-126edf511060.png)
26+
Figure 2

XLS-0022-api-versioning/README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<pre>
2+
xls: 22
3+
title: rippled API Versioning
4+
description: The API version number allows for evolving the `rippled` API while maintaining backward compatibility
5+
author: Elliot Lee (intelliot), Peng Wang (pwang200)
6+
status: Final
7+
category: Protocol
8+
created: 2021-08-11
9+
</pre>
10+
11+
# rippled API Versioning
12+
13+
rippled offers an API (application programming interface) that apps use to integrate with the XRP Ledger. In order to evolve and improve this API over time, while providing consistency and ensuring backward compatibility for clients, the API shall be versioned with an `API version number`.
14+
15+
For JSON-RPC and WebSocket (the most commonly-used interfaces), the API version number field is called `"api_version"`.
16+
17+
### JSON-RPC
18+
19+
```json
20+
{
21+
"method": "...",
22+
"params": [
23+
{
24+
"api_version": 1,
25+
"...": "..."
26+
}
27+
]
28+
}
29+
```
30+
31+
Notice that "api_version" is [not a top-level field](https://github.com/ripple/rippled/issues/3065).
32+
33+
### WebSocket
34+
35+
```json
36+
{
37+
"api_version": 1,
38+
"id": 4,
39+
"command": "...",
40+
"...": "..."
41+
}
42+
```
43+
44+
Following the [WebSocket request format](https://xrpl.org/request-formatting.html), it is placed at the top level.
45+
46+
### rippled command line
47+
48+
The RPC command and its parameters are parsed first. Then, a JSON-RPC request is created. rippled shall not support multiple versions of the command-parameter parsers, so the JSON-RPC requests will have one API version number. The latest API version number shall be used. Under the hood, rippled shall insert the `"api_version"` field internally.
49+
50+
### gRPC
51+
52+
The version number for gRPC is specified as part of the package name of the gRPC service definition (in .proto files). The .proto files of different versions shall be placed in version-specific folders.
53+
54+
Multiple versions of the API are created by constructing multiple services, located in different namespaces. From gRPC's perspective, they are simply different services. All of the services can be registered to a single gRPC server.
55+
56+
## Specification
57+
58+
**The API version number shall be a single unsigned integer.** This is simpler than the major.minor.patch format, which is already used for versions of rippled itself. When it comes to API versions, there is no need for additional complexity beyond a single integer.
59+
60+
**The API version number shall be increased if, and only if, we introduce one or more breaking changes to the API.** When the version number is increased, it is increased by one.
61+
62+
**The lowest valid version number shall be 1.** The version number 0 is invalid.
63+
64+
**rippled shall support a range of versions with consecutive version numbers.** At the moment, the range is [1, 1].
65+
66+
**Client requests targeting an API version that is out of the supported version range shall be rejected.** For safety and ease of understanding, we do not allow "forward compatibility" where, if a version number in the request is higher than the supported range, we would lower its version number to the highest supported version number. Most clients know in advance which rippled servers they are connecting to (indeed, this is required for the XRPL security model). So it is unlikely that they will "mistakenly" make a request to a server that does not support the API version that they require. And if they do, it is better to respond with an error: the client can then choose to handle the error in a way that is appropriate for its use case.
67+
68+
**Client targeting APIs with versions 2 and above shall specify the version number in their requests.** The WebSocket and JSON-RPC (HTTP) requests shall include the version number in the request payloads.
69+
70+
**Requests without a version number shall be handled as version 1 requests.** This provides backward compatibility to the time when API version numbers did not yet exist.
71+
72+
**Responses do not need to include the API version number.** This saves some bandwidth and encourages the "best practice" of having the client track its requests with the `id` field.
73+
74+
**When a client sends multiple requests over a persistent connection (e.g. WebSockets), each request may use a different API version number.** This gives clients flexibility, with the ability to "progressively" update to new API versions in specific requests, without changing their entire integration.
75+
76+
**When using the rippled command line interface, the latest API version shall be used.** The command line interface is typically used for development, debugging, and one-off requests. For simplicity and to ensure that developers always pay attention to the evolution of the API, these requests shall use the latest API version.
77+
78+
**An API version that available in a stable release of rippled is considered "ready".** From the client's perspective, alpha/beta API versions generally should not exist.
79+
80+
## Implementation Details
81+
82+
There are four (4) RPC interfaces:
83+
84+
1. JSON-RPC (HTTP)
85+
2. WebSocket
86+
3. rippled command line
87+
4. gRPC
88+
89+
The API version number is a single 32-bit unsigned integer. A range of consecutive API versions are supported by rippled. The lower and upper bounds of the range shall be hardcoded. Different rippled software versions may support different API version ranges.
90+
91+
For JSON-RPC and WebSocket, when a client requests an API version that is out of the supported range, the returned error message shall include the string "Unsupported API version", the version number targeted by the request, and the lower and upper bounds of the supported range.
92+
93+
## What is considered a breaking change?
94+
95+
- Deleting (removing), renaming, changing the type of, or changing the meaning of a field of a request or a response.
96+
- Changing the order of position-based parameters, or inserting a new field in front of existing position-based parameters.
97+
- Deleting or renaming an API method (function).
98+
- Changing the behavior of an API method in a way that is visible to existing clients.
99+
- Changing HTTP status codes[^1].
100+
101+
gRPC only:
102+
103+
- Changing a proto field number.
104+
- Deleting or renaming an enum or enum value.
105+
- Moving fields into or out of a oneof, split, or merge oneof.
106+
- Changing the label of a message field, i.e. optional, repeated, required.
107+
- Changing the stream value of a method request or response.
108+
- Deleting or renaming a package or service.
109+
110+
## What is not a breaking change?
111+
112+
- Adding a new field to a request or response message, if it is not a position-based parameter.
113+
- Adding a new API method (function).
114+
115+
## References
116+
117+
- [Documentation: API Versioning](https://xrpl.org/request-formatting.html#api-versioning)
118+
- [API versioning #3155 (rippled PR)](https://github.com/ripple/rippled/pull/3155): Merged and released in [rippled v1.5.0](https://github.com/ripple/rippled/releases/tag/1.5.0)
119+
- [Original Requirements](https://github.com/pwang200/RippledRPCDesign/blob/API_versioning/requirement/requirements.md)
120+
- [Original Design Document](https://github.com/pwang200/RippledRPCDesign/blob/API_versioning/design/design.md)
121+
122+
[^1]:
123+
Changes to response status codes. For example, this is a breaking change:
124+
**Before:** POST /values returns 400 for missing property
125+
**After:** POST /values returns 409 for missing property
126+
[Reference](https://community.blackbaud.com/blogs/69/3219)
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<pre>
2+
xls: 49
3+
title: Multiple Signer Lists
4+
description: A proposal to enable multiple signer lists per account on the XRP Ledger, allowing different signer lists to authorize specific transaction types.
5+
author: Mayukha Vadari <mvadari@ripple.com>
6+
discussion-from: https://github.com/XRPLF/XRPL-Standards/discussions/144
7+
status: Draft
8+
category: Amendment
9+
created: 2023-11-13
10+
</pre>
11+
12+
# Multiple Signer Lists
13+
14+
## Abstract
15+
16+
The XRP Ledger currently only supports one global signer list per account. However, many users (such as token issuers) require more granularity. For example, they might want to have one signer list with the ability to mint new tokens, and another signer list with the ability to create and edit trustlines.
17+
18+
This document describes a proposal for supporting multiple signer lists per account. The current system of global signer lists will continue to be supported, but we propose adding **per-transaction-type signer lists**. Accounts can set up signer lists that only have the power to send **transactions of one specific type** on behalf of the account.
19+
20+
This proposal is related to [XLS-31d](https://github.com/XRPLF/XRPL-Standards/discussions/77), but broader in scope.
21+
22+
## 1. Overview
23+
24+
We propose modifying one ledger object and one transaction:
25+
26+
- `SignerList` ledger object
27+
- `SignerListSet` transaction
28+
29+
This change will require an amendment.
30+
31+
The important considerations to keep in mind are:
32+
33+
- `rippled` must be able to retrieve all possible signer lists for a transaction type quickly and easily, in order to check if a transaction has a valid multisign list.
34+
- Any signer list that can sign transactions can drain the account's XRP via fees.
35+
36+
## 2. On-Ledger Object: **`SignerList`**
37+
38+
There is no change to the shape of a [`SignerList` ledger object](https://xrpl.org/signerlist.html), only in how it's used.
39+
40+
### 2.1. Fields
41+
42+
As a reference, the **`SignerList`** object currently has the following fields:
43+
44+
| Field Name | Required? | JSON Type | Internal Type |
45+
| ------------------- | --------- | --------- | ------------- |
46+
| `LedgerIndex` | ✔️ | `string` | `HASH256` |
47+
| `LedgerEntryType` | ✔️ | `string` | `UINT16` |
48+
| `SignerEntries` | ✔️ | `array` | `STARRAY` |
49+
| `SignerQuorum` | ✔️ | `number` | `UINT32` |
50+
| `SignerListID` | ✔️ | `number` | `UINT32` |
51+
| `OwnerNode` | ✔️ | `string` | `UINT64` |
52+
| `PreviousTxnID` | ✔️ | `string` | `HASH256` |
53+
| `PreviousTxnLgrSeq` | ✔️ | `number` | `UINT32` |
54+
55+
The ledger index of this object is calculated by hashing together the owner's account ID with the value of `0`.
56+
57+
The only field whose usage is changing is `SignerListID`. All other fields will be used the same as they are now.
58+
59+
#### 2.1.1. `SignerListID`
60+
61+
This field is currently always set to `0`. The original [`Multisign` implementation](https://xrpl.org/known-amendments.html#multisign) only allowed for one signer list per account, but left the door open for the possibility of more.
62+
63+
We propose that this field is instead used for the transaction type that the signer is allowed to sign for, with `0` being the value for the global signer list (to ensure backwards compatibility). There is enough space in `SignerListID` for this field, because `TxType` is a `UInt16` and `SignerListID` is a `UInt32`. Since the `UInt32` is so much larger than the `UInt16`, there is extra room in the valid values for additional signer list usage proposals. The value of this field will also be used in the `index` calculation.
64+
65+
One problem: `Payment` has transaction type `0`, which would conflict with the global signer list. To get around that, we will instead use `1+TxType` in the `SignerListID` field. It is then very easy to check whether a multisign transaction is valid: the code can check the global signer list (look at the signer list with index `account + 0`), and the transaction-type-specific signer list (look at the signer list with index `account + (1+TxType)`).
66+
67+
Each additional `SignerList` that an account owns will, of course, cost an additional owner reserve (2 XRP at the time of writing).
68+
69+
## 3. Transaction: **`SignerListSet`**
70+
71+
The [`SignerListSet` transaction](https://xrpl.org/signerlistset.html) already exists on the XRPL. We propose a slight modification to support per-transaction-type signer lists.
72+
73+
### 3.1. Fields
74+
75+
As a reference, the **`SignerListSet`** transaction already has the following fields:
76+
77+
| Field Name | Required? | JSON Type | Internal Type |
78+
| ----------------- | --------- | --------- | ------------- |
79+
| `TransactionType` | ✔️ | `string` | `UInt16` |
80+
| `SignerEntries` | ✔️ | `array` | `STARRAY` |
81+
| `SignerQuorum` | ✔️ | `number` | `UInt32` |
82+
83+
We propose adding a new optional field:
84+
| Field Name | Required? | JSON Type | Internal Type |
85+
|------------|-----------|-----------|---------------|
86+
|`TransactionTypeBitmask` | |`array`|`HASH256`
87+
88+
#### 3.1.1. `TransactionTypeBitmask`
89+
90+
This field accepts a bitmask of transaction types, much like the [`HookOn` field](https://xrpl-hooks.readme.io/docs/hookon-field). A `0` bit is "on" and a `1` bit is "off". A value of `0` changes the global signer list. All other values change the many signer lists of the transactions they apply to, so that it is easier to modify many signer lists at once. The JSON will show a list of transactions.
91+
92+
## 4. Security
93+
94+
One important fact to remember is that any signer list that can sign transactions can drain the account's XRP via fees. This was why multiple signer lists were never implemented originally. There is [an open issue](https://github.com/XRPLF/rippled/issues/4476) proposing potential ways to prevent accidental high fees on transactions.
95+
96+
Also, any signer list that is added to `SignerListSet` can effectively give themselves powers over any other transaction(s) they desire.
97+
98+
# Appendix
99+
100+
## Appendix A: FAQ
101+
102+
### A.1: Should global signer lists still be able to send transactions that have specific signer lists enabled?
103+
104+
Yes, because global signer lists should be able to act exactly like master and regular keys. This proposal does not support changing that.
105+
106+
### A.2: Why not also use a bitmask for storage?
107+
108+
This design was strongly considered, but this spec is easier to use and understand. See Appendix B for more details.
109+
110+
### A.3: Why not just take a transaction type in the `TransactionTypeBitmask` field?
111+
112+
That was part of the original design, because it would be more user-friendly and easier to read. It was changed to allow accounts to modify multiple signer lists with one transaction.
113+
114+
### A.4: Can you remove the global signer list after removing the master and regular key?
115+
116+
No, you need to go through the standard blackhole procedure (setting the regular key to `ACCOUNT_ZERO`).
117+
118+
Theoretically, an account could only have a specific signer list on at least one of `SignerListSet`/`SetRegularKey`/`AccountSet` so that the blackholing can be changed. However, this addition seems unnecessary since the standard blackhole procedure already exists.
119+
120+
### A.5: Why not use crypto-conditions?
121+
122+
This was briefly considered, but we decided to go with this design instead. See Appendix C for more details.
123+
124+
## Appendix B: Bitmasks for `SignerListID`
125+
126+
Another design we developed (and seriously considered) was using a bitmask to determine which transaction types a signer list could sign for. This took inspiration from the [`HookOn` field](https://xrpl-hooks.readme.io/docs/hookon-field) in the hooks proposal.
127+
128+
The ledger modifications necessary for this design:
129+
130+
- The ledger object hash (`index`) is now derived from the sequence of the transaction that created the signer list (similar to how escrow hashes are derived). This sequence is stored in the `SignerListID` field.
131+
- Modifying or deleting a signer list that isn't the global one (instead of creating a new one) requires specifying the `SignerListID` in the `SignerListSet` transaction.
132+
- Using a signer list that isn't the global one requires specifying the `SignerListID` in the transaction (a new global optional field).
133+
134+
Ultimately, due to the pros and cons, we decided against this spec. If you have strong feelings about this design (positive _or_ negative), please comment, because it's still in consideration.
135+
136+
### B.1. Pros and Cons
137+
138+
**Existing Spec**
139+
140+
- Pros
141+
- Ease of use and understandability - same as existing processes
142+
- Only one signer list can access each transaction (technically two if you include the global signer list)
143+
- Cons
144+
- One signer list per transaction, even if the same signer list is used for multiple transactions
145+
- One reserve per transaction
146+
- Only one signer list can access each transaction
147+
148+
**Bitmask**
149+
150+
- Pros
151+
- One signer list object regardless of how many transactions it controls (easier on ledger resources)
152+
- One reserve per signer list
153+
- Multiple signer lists can access each transaction
154+
- Cons
155+
- More UX changes - you need to specify the `SignerListID` in the transaction. This is all less compatible with the existing UX for the global signer list.
156+
- Multiple signer lists can access each transaction (this could get messy and is more difficult to keep track of)
157+
- A larger change to the current usage of signer lists
158+
- What happens if/when we reach 256 transactions?
159+
160+
## Appendix C: Crypto-Conditions
161+
162+
Using crypto-conditions for implementing per-transaction-type multisign was considered, but it seemed overly complex for the use-cases that people have. If a crypto-condition-based multisign approach is implemented, it should probably be integrated into all signatures, and apply to both multi-sign _and_ single-sign.

0 commit comments

Comments
 (0)