-
Notifications
You must be signed in to change notification settings - Fork 241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem: missing ADR for precompiled #1191
Draft
thomas-nguy
wants to merge
4
commits into
crypto-org-chain:main
Choose a base branch
from
thomas-nguy:thomas/adr-0010
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+167
−14
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# ADR 010: Custom precompiled for app-chain | ||
|
||
## Changelog | ||
* 2023-10-02: first draft | ||
|
||
## Context | ||
|
||
Cronos is an EVM-compatible built on Cosmos SDK. The "ethermint" module allows a full compatibility and interoperability with Ethereum. However, it comes with the sacrifice of cosmos native features or cosmos interchain features (IBC) | ||
as end-users are not able to access them through an ethereum transaction. The solution is to provide precompile, allowing users to access to cosmos features through smart contracts. | ||
A precompiled behave like a smart contract, it is designed by an address and can be invoked by other smart contracts. The difference is that its execution is not inside a smart contract. | ||
App-chain specific logics can be embedded to the pre-compiled so that it could be used to expose cosmos native features at the EVM layer. | ||
|
||
|
||
## Decision | ||
|
||
### Fork go-ethereum for stateful precompiled support | ||
|
||
One of the major difficulties in supporting pre-compiled is the lack of flexibility in geth for defining custom precompiled and its non-ability to modify the state. | ||
We made the choice of forking geth and implement additional interfaces so that app-chain can define its own precompiled. | ||
|
||
The PR [#7](https://github.com/evmos/go-ethereum/pull/7) implements the ability to set custom precompiled to the EVM. | ||
while this PR [#10](https://github.com/evmos/go-ethereum/pull/10) allows the precompiled to modify the state (for stateful precompiled) | ||
|
||
In the future, we are planning to maintain the following fork permanently | ||
`github.com/evmos/go-ethereum` | ||
|
||
### Implement pre-compiled for cosmos native module | ||
|
||
We provide pre-compiles for cosmos native module such as bank module. | ||
|
||
```solidity | ||
|
||
interface IBankModule { | ||
function mint(address,uint256) external payable returns (bool); | ||
function balanceOf(address,address) external view returns (uint256); | ||
function burn(address,uint256) external payable returns (bool); | ||
function transfer(address,address,uint256) external payable returns (bool); | ||
} | ||
|
||
|
||
``` | ||
The input and output of methods are mapped with those defined cosmos native transactions. | ||
Because the precompiled is called at the evm layer, it uses the evm authentication instead of the cosmos authentication for transactions. | ||
It is important to define for each precompiled module the range of action "authorized" for each request. | ||
For the bank module, the precompiled is authenticated with `msg.sender` address. The smart contracts or users can only mint/burn cosmos coins denoted by the denom `evm/0x{msg.sender}` or transfer coins from the `0x{msg.sender}` account. | ||
|
||
|
||
To call a precompiled from a smart contract, create an instance of the module interface with the precompiled address. | ||
The methods are ABI encoded, and can be called directly as calling the function through the interface: | ||
|
||
```solidity | ||
|
||
address constant bankContract = 0x0000000000000000000000000000000000000064; | ||
IBankModule bank = IBankModule(bankContract); | ||
bank.transfer(msg.sender, recipient, amount); | ||
|
||
``` | ||
|
||
|
||
### Implement pre-compiled for cosmos interchain communication | ||
|
||
#### Relayer | ||
One of the benefits of supporting precompiled for IBC is that it would be possible to track the change of state triggered by the ibc transaction with ethereum receipts. | ||
|
||
For that reason we are exposing all relayer related actions to the evm layer. An action is defined by a 4 bytes prefix. | ||
|
||
```go | ||
|
||
const ( | ||
prefixSize4Bytes = 4 | ||
// Client | ||
prefixCreateClient = iota + 1 | ||
prefixUpdateClient | ||
prefixUpgradeClient | ||
prefixSubmitMisbehaviour | ||
// Connection | ||
prefixConnectionOpenInit | ||
prefixConnectionOpenTry | ||
prefixConnectionOpenAck | ||
prefixConnectionOpenConfirm | ||
// Channel | ||
prefixChannelOpenInit | ||
prefixChannelOpenTry | ||
prefixChannelOpenAck | ||
prefixChannelOpenConfirm | ||
prefixChannelCloseInit | ||
prefixChannelCloseConfirm | ||
prefixRecvPacket | ||
prefixAcknowledgement | ||
prefixTimeout | ||
prefixTimeoutOnClose | ||
) | ||
|
||
``` | ||
|
||
-> TODO describe the change in go-relayer | ||
|
||
#### ICA | ||
|
||
The ICA precompiled interface is defined by : | ||
|
||
```solidity | ||
interface IICAModule { | ||
event SubmitMsgsResult(uint64 seq); | ||
|
||
function registerAccount(string calldata connectionID, string calldata version) external payable returns (bool); | ||
function queryAccount(string calldata connectionID, address addr) external view returns (string memory); | ||
function submitMsgs(string calldata connectionID, bytes calldata data, uint256 timeout) external payable returns (uint64); | ||
} | ||
``` | ||
The request is authenticated by `msg.sender` and it can only send request on behalf of this account. | ||
|
||
The calldata in `submitMsgs` represents the cosmos proto-encoded message to be sent to the destination app-chain. Only one message can be sent at the moment. | ||
|
||
For example to call a bank transaction to another app-chain : | ||
|
||
```solidity | ||
|
||
function ICACallBank(string memory connectionID, uint256 timeout, params.....) public returns (uint64) { | ||
msg = bankMsgSendProto.encode(params) | ||
lastSeq = ica.submitMsgs(connectionID, msg, timeout); | ||
return lastSeq; | ||
} | ||
|
||
``` | ||
|
||
In case of ICA, it is also important to be able to track the result of the transaction `submitMsgs` so that the user or the smart contract can respond accordingly. | ||
The function `submitMsgs` returns a sequence number that can be used by the user or smart contract to track the state of the msg using the precompiled `ICACallback`. | ||
|
||
|
||
```solidity | ||
interface IICACallback { | ||
function onPacketResultCallback(uint64 seq, bool ack) external payable returns (bool); | ||
} | ||
|
||
``` | ||
|
||
|
||
### Precompiled gas cost | ||
|
||
A precompiled is basically an op-code at the evm layer thus, it has a constant cost. Because a stateful precompiled can change the state, it is much harder to define a specific cost. | ||
To be fair, we are evaluating the cost of a pre-compile based on the average cost of the cosmos transaction in the past history. | ||
Future work aim to provide a more accurate cost on the pre-compiled | ||
|
||
## Further discussions | ||
|
||
- Disabling cosmos native modules in cronos | ||
- Establishing a standard for ibc for evm based chain (relayer) | ||
- Extending the usage of pre-compile for broader use cases | ||
|
||
## References | ||
|
||
* https://github.com/crypto-org-chain/cronos/pull/837 | ||
* https://github.com/crypto-org-chain/cronos/pull/1163 | ||
* https://github.com/crypto-org-chain/cronos/pull/1014 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mmsqe Not sure why we are using a prefix based encoding rather than abi encoding like for all the other precompiled?