Multichain is a collection of functions, types, interfaces, and runtimes that can be implemented for any blockchain. Those familiar with the Rosetta spec by Coinbase will note similarities in goals. However, multichain's scope is limited to accounts, contract calls, and sending transactions — there is no block data extraction. Moreover, the chain (Harmony) would have to implement the appropriate functions to Ren's multichain repo as a pull request and undergo their review. The Ren Project notes that once Harmony has integrated with the multichain API, we have the possibility for support in the RenVM.
To help bridge the gap between Harmony and other chains, we must explore ways to integrate with chain agnostic interfaces. Having an API that is standard across multiple chains (notably BTC & ETH) will help reduce the friction of getting assets onto Harmony. This document will provide a high level (but technical) overview of the components needed to integrate with Multichain.
What APIs would be available:
What extra components are needed:
- Localnet with a docker file
- Supplementary testing account just for localnet (not funded on testnet)
- Gas price estimate RPC (optional)
What will NOT be built:
- Staking Compatability
- Block data extraction
- UTXO APIs
As a reference, we can follow this guide.
Note that we should only rely on imports from the core protocol repo as the go-SDK is subject to change soon.
We will use JSON-RPC 2.0 to communicate with a Harmony node.
We can choose to implement our own requester, or we can re-use solana's RPC requester here as they also use JSON-RPC 2.0.
We will be integrating with 1 shard ONLY (defined as the target-shard
). This reduces the complexity of transaction functionalities and should be sufficient for the goals of multichain.
We may choose to add it as an option when creating a
Client
and propagating it to theTxBuilder
(explained in the Account API). Alternatively, we can just hard code the shard to beacon-shard as it has the most assets.
Multichain requires a docker file to run a node for a chain's test. All docker files will get placed here and get triggered from here.
We do not have any easy way to run a localnet like ganache, therefore we will just replicate the debug localnet (from here) using the latest stable binary within a docker image (exposing the target-shard
's explorer port) to provide a node for tests. Some of the leg work has been done here & here, however, some integration needs to be done to fit the necessary functionality.
The interface to implement is EncoderDecoder
, which consists of the Encoder
and Decoder
interfaces.
Note that we should use the Bech-32 addresses (a string) cast as Address
and the byte representation of the Bech-32 addresses cast as RawAddress
. This way, we should not have to redefine/reimplement the Address
and RawAddress
types & methods. The alternative is to just use the already implemented ETH addresses here and re-export the Address
.
Since we are using the Bech-32 addresses, it should be easy to create a simple address Encoder & Decoder. If we use the built-in ETH address, we do not have to implement a decoder/encoder — all we have to do is re-export it (similar to what Celo has done here).
The interfaces to implement are: Tx
, TxBuilder
, and Client
.
Note that for signing transactions, we are always in post EIP115 epoch, therefore we must always use the EIP115 signer found here.
For the Tx
interface, the Hash
, From
, To
, Value
, Nonce
, and Payload
methods should be easy to implement with a wrapper around the Harmony Transaction
object. The Sighashes
method's content can be found here. The Sign
method's implementation can be found here & here. Lastly, the Serialize
method is simply the RLP encoding to bytes to be submitted to the mem pool (example here).
Note that for signing transactions, we are always in post EIP115 epoch, therefore we can always use the EIP115 signer found here. Homestead signers are to be ignored. For the ChainID required by the EIP115 signer, we can store it as an attribute of the
Tx
object and set it upon building a new transaction.
For the TxBuilder
interface, we only have to implement the BuildTx
method. Note that we must include the Chain ID for the EIP115 signer; this can be fetched from the node's metadata within the BuildTx
method. We may also want to include an additional method for TxBuilder
to fetch the appropriate nonce for the BuildTx
param.
For the Client
interface, the Tx
method is simply a getTransactionByHash
RPC call. The SubmitTx
method is not clear as to if it should block until confirmation of tx or not. Since most APIs do not block on the submission of a transaction, we should implement it as such.
The interface to implement is Caller
. The only method to implement is CallContract
. Note that the CallData
could be a byte or marshaled version of the call data struct used by the call
RPC.
Note that we should keep the address consistent. Our RPC layer takes in hex addresses instead of the Bech-32 addresses for the
CallArgs
. For consistency, we may want to take the call arguments in multichain as Bech-32 (fromAddress
API) and convert them appropriately for the RPC call.Also note that it may be worth it to implement the
CallContract
under theClient
object from the Account API as some state variables may be shared.
The interface to implement is Estimator
. The only method to implement is EstimateGasPrice
. Note that we currently do not have a way to estimate the gas price. We can either hard code some value in multichain (citing 5sec block time as an excuse), or we can implement an RPC to get the average gas price in the mem-pool and call that as part of the EstimateGasPrice
method.
Add ONE
as a supported asset here & ensure tests pass for ALL supported chains.
Discription | Target Date |
---|---|
Address API | 9/3 |
Docker Localnet for Tests | 9/4 |
Account API | TBD |
Gas API [+ Gas Price Estimator RPC] | TBD |
Contract API + Final Touchups | TBD |
This is where updates will be posted regarding current progress & hurdles.