After years of working on asset addition, we determined it was not possible to support the vast majority of blockchains with a single high-level abstraction. Blockchains contain many network-specific nuances that make widespread assumptions about the representation of blockchain data useless or confusing.
The Rosetta APIs are based on a series of low-level abstractions that can be combined to provide powerful tools like building blocks. Without this low-level specificity, it would not be possible to recognize and perform a wide variety of complex operations on a large group of blockchains.
No Predefined Operation Types
The Rosetta interface does not restrict implementations
to use a predefined set of types to describe network-specific activity.
PAYMENT could be a predefined type that could
be required for all implementers to apply to network-specific
transactions. While this sounds appealing and feasible for a simple type
PAYMENT, the task of producing such a set
of types can quickly become very complex and controversial. Instead, the
interface puts the burden on the client to apply
whatever types they feel best apply to the standardized
operations that compose each transaction.
Signed Operation Amounts
Although there are no predefined operation types in the interface, an explicit attempt is made to make balance reconciliation much easier: using signed operation amounts. This means that all operations within a transaction must clearly specify the balance change that results from that operation are explicitly credit or debits to a specified account.
Single Party, Linked Operations
All operations in the interface can affect at most 1 account but can be linked to any number of other operations. To represent network-specific operations that are inherently multi-participant (a network-specific transfer that has a sender and recipient specified in a single op), this entails creating an explicit operation for each account involved.
At a high-level, this means reducing account-based blockchains to something resembling ledger accounting (all credits have debits). While this approach may seem burdensome for simple payments, the generality of this design allows for capturing the structure of complicated on-chain interactions more closely to how they are represented natively on-chain without imposing more restrictions on the operation model. This single operation abstraction for all accounting types also means that downstream processing does not require conditional parsing on different operation abstractions.
Transaction Fees are Just Operations
For blockchains where there is no explicit fee payer, where there are multiple fee payers, where fees can be paid in multiple currencies, or where fee payment is made by one of many parties in a transaction, it becomes complicated to represent a fee payment as a transaction property. Thus, all transaction fees are represented exclusively as operations.
Operation Status, Not Transaction Status
Indication of status on the transaction implies that all operations within that transaction atomically succeed or fail. While this is often true on blockchains without smart contracting, it is not always the case on blockchains that support generalized smart contracting. In Ethereum, transactions can fail anytime during execution and changes are only rolled back when explicitly indicated to do so in the smart contract itself. Requiring that implementers have atomic transaction success/failure is a pretty heavy handed restriction that could limit innovation.