lightsail-network / java-stellar-sdk

The Java Stellar SDK library provides APIs to build transactions and connect to Horizon and Soroban-RPC Server.
https://javadoc.io/doc/network.lightsail/stellar-sdk
Apache License 2.0
175 stars 160 forks source link

Protocol 22: Smoothing out breaking changes #651

Closed Shaptic closed 1 week ago

Shaptic commented 2 weeks ago

Protocol 22: Additional Changes

Interface Compatibility

In the previous announcement about the upcoming changes for Protocol 22, we made a significant oversight in compatibility. When a user upgrades to the latest version of your SDK, their code will now only be compatible with a v22.* version of the backend services they're connected to. This means they can only upgrade exactly when their RPC/Horizon provider upgrades, which is a violation of the previous compatibility guarantees we provide the ecosystem. That guideline essentially boils down to:

You can safely upgrade your SDK prior to the next major version upgrade.

To maintain this principle, we are releasing new release candidates of Horizon and Stellar RPC to increase the backwards-compatibility of various interfaces and make it easier for people to have a smooth upgrade. We are also asking SDK maintainers to use these new, smoother interfaces to ensure that users can upgrade to the latest version of their SDKs without requiring their use exclusively with Protocol 22-compatible software. In other words, users should be able to upgrade today and not rely on v22 versions of Horizon or RPC deployed for their dependent network.

Stellar RPC: v22.0.0-rc3

In this release, we are reintroducing fields that previously constituted breaking changes:

  1. Previously, in RC2, getTransactions would encode createdAt as a string instead of number. This change has been reverted. The next release will continue to encode it as a number (specifically, a uint32).
  2. Previously, getVersionInfo would now use camelCasing over snake_case. This change is now additive. The response schema in the next release will contains both variants:
    interface GetVersionInfoResponse {
    version: string;
    commitHash: string;
    buildTimestamp: string;
    captiveCoreVersion: string;
    protocolVersion: number; // uint32
    /// Deprecated field names:
    commit_hash: string;
    build_timestamp: string;
    captive_core_version: string;
    protocol_version: number; // uint32
    }
  3. Previously, getEvents replaced pagingToken with cursor within each event for pagination. This change is now additive, and the response schema will now include both fields. Please note that the id field will continue to match both the old pagingToken and the new cursor.
  4. Previously, simulateTransaction removed the deprecated cost field. This change remains, because it does not require a "lockstep" upgrade with their provider: users can acquire the new costs by extracting them from the transaction resource data. For example,
    
    // before:
    let result = await server.simulateTranasction(tx);
    // assume result.error === undefined
    let cost: rpc.Api.Cost = result.cost;

// after: let resources = result.transactionData.build().resources(); let cost: rpc.Api.Cost = { cpuInsns: resources.instructions().toString(), memBytes: (resources.readBytes() + resources.writeBytes()).toString(), };

5.  Previously, the  `getLedgerEntry` endpoint had been removed entirely. **This change remains,** because clients can transition to `getLedgerEntries` without waiting on a provider upgrade. For example,
```bash
# before, the JSON-RPC request would have
{
  # ...
  "method": "getLedgerEntry", 
  "params": {
    "key": "insert base64 xdr here"
  }
}

# now it will have
{
  # ...
  "method": "getLedgerEntries", 
  "params": {
    "keys": [ "insert base64 xdr here" ]
  }
}

Horizon: v22.0.0-rc2

Similarly, we are reintroducing fields that previously constituted breaking changes:

  1. Previously, the /transaction_async endpoint changed errorResultXdr :arrow_right: error_result_xdr. This change is now additive, and in the next release the response schema will have both fields.
  2. Previously, the /asset endpoint dropped num_accounts and amount, and the /transactions/:id endpoint dropped valid_before and valid_after. These changes remain, because the values still exist in other locations. Namely, num_accounts and amount are inside of accounts, while valid_before and valid_after are equivalent to the values in the preconditions object.

Maintainer Actions

Please ensure that users can upgrade to your latest SDK version without depending exclusively on the breaking schemas in Horizon v22.0.0-rc1 and Stellar RPC v22.0.0-rc2. Users should be able to upgrade today and not rely on v22 versions of Horizon or RPC deployed for their dependent network.

Please release your Protocol-22 compatible software releases as release candidates, because things are still subject to change.

As outlined above, breaking changes are still acceptable if there is an alternative, client-side way of acquiring the same field but not if the field is only present in a v22 version of the backend service. These are part of the natural transition to a new version that clients should be prepared for.

A concrete example: someone with an existing codebase may have code written that uses the createdAt field returned by rpc.getTransaction. If they upgrade to the latest version, their code will break because the field is now strictly typed as a string. And yet, if they were to update their code accordingly, their code would not function unless they pointed at a v22 RPC. This is the lockstep upgrade we are trying to avoid. This is in contrast to a change like cost being removed, because they can write code that works on both v21 and v22 RPCs by using the existing transactionData field to migrate.

Reference Implementations

JavaScript: stellar/js-stellar-sdk#1084