Skip to content

Commit 2c183bc

Browse files
Provide EVM support for some linera features (#3847)
## Motivation The Linera features need to be provided for EVM. Some of this is done here. ## Proposal The following is provided: * validation_round * chain_ownership * chain_id * application_creator_chain_id * read_data_blob * assert_data_blob_exists The precompile is extended for that purpose and the handling of the various cases is reorganized for clarity. ## Test Plan A test for the features has been provided in the CI. ## Release Plan The goal is to provide all this for TestNet 3. ## Links None.
1 parent 12c1d23 commit 2c183bc

File tree

15 files changed

+1460
-287
lines changed

15 files changed

+1460
-287
lines changed

Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ lru = "0.12.3"
122122
num-bigint = "0.4.3"
123123
num-format = "0.4.4"
124124
num-traits = "0.2.18"
125-
num_enum = "0.7.3"
126125
octocrab = "0.42.1"
127126
oneshot = "0.1.6"
128127
pathdiff = "0.2.1"

examples/Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

linera-base/src/crypto/hash.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ impl TryFrom<&[u8]> for CryptoHash {
135135
}
136136
}
137137

138+
impl From<CryptoHash> for [u8; 32] {
139+
fn from(crypto_hash: CryptoHash) -> Self {
140+
crypto_hash.0 .0
141+
}
142+
}
143+
138144
impl From<[u64; 4]> for CryptoHash {
139145
fn from(integers: [u64; 4]) -> Self {
140146
CryptoHash(crate::crypto::u64_array_to_be_bytes(integers).into())

linera-execution/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ linera-views.workspace = true
5050
linera-views-derive.workspace = true
5151
linera-witty = { workspace = true, features = ["log", "macros"] }
5252
lru.workspace = true
53-
num_enum.workspace = true
5453
oneshot.workspace = true
5554
prometheus = { workspace = true, optional = true }
5655
proptest = { workspace = true, optional = true }
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright (c) Zefchain Labs, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
pragma solidity ^0.8.0;
4+
5+
import "./LineraTypes.sol";
6+
7+
// This library provides Linera functionalities to EVM contracts
8+
// It should not be modified.
9+
10+
// The Precompile keys below correspond to the BCS serialization of
11+
// the `PrecompileTag` in `linera-execution/src/evm/revm.rs`.
12+
// (0,0): chain_id
13+
// (0,1): application_creator_chain_id
14+
// (0,2): chain_ownership
15+
// (0,3): read data blob
16+
// (0,4): assert data blob exists
17+
// (1,0): try_call_application
18+
// (1,1): validation round
19+
// (1,2): send_message
20+
// (1,3): message_id
21+
// (1,4): message_is_bouncing
22+
// (2,0): try_query_application
23+
library Linera {
24+
25+
function inner_chain_id(uint8 val) internal returns (LineraTypes.ChainId memory) {
26+
address precompile = address(0x0b);
27+
bytes memory input1 = new bytes(2);
28+
input1[0] = bytes1(uint8(0));
29+
input1[1] = bytes1(val);
30+
(bool success, bytes memory output1) = precompile.call(input1);
31+
require(success);
32+
return LineraTypes.bcs_deserialize_ChainId(output1);
33+
}
34+
35+
function chain_id() internal returns (LineraTypes.ChainId memory) {
36+
return inner_chain_id(uint8(0));
37+
}
38+
39+
function application_creator_chain_id() internal returns (LineraTypes.ChainId memory) {
40+
return inner_chain_id(uint8(1));
41+
}
42+
43+
function chain_ownership() internal returns (LineraTypes.ChainOwnership memory) {
44+
address precompile = address(0x0b);
45+
bytes memory input1 = new bytes(2);
46+
input1[0] = bytes1(uint8(0));
47+
input1[1] = bytes1(uint8(2));
48+
(bool success, bytes memory output1) = precompile.call(input1);
49+
require(success);
50+
return LineraTypes.bcs_deserialize_ChainOwnership(output1);
51+
}
52+
53+
function read_data_blob(bytes32 hash) internal returns (bytes memory) {
54+
address precompile = address(0x0b);
55+
bytes memory input1 = new bytes(2);
56+
input1[0] = bytes1(uint8(0));
57+
input1[1] = bytes1(uint8(3));
58+
bytes memory input2 = abi.encodePacked(input1, hash);
59+
(bool success, bytes memory output1) = precompile.call(input2);
60+
require(success);
61+
return output1;
62+
}
63+
64+
function assert_data_blob_exists(bytes32 hash) internal {
65+
address precompile = address(0x0b);
66+
bytes memory input1 = new bytes(2);
67+
input1[0] = bytes1(uint8(0));
68+
input1[1] = bytes1(uint8(4));
69+
bytes memory input2 = abi.encodePacked(input1, hash);
70+
(bool success, bytes memory output1) = precompile.call(input2);
71+
require(success);
72+
assert(output1.length == 0);
73+
}
74+
75+
function try_call_application(bytes32 universal_address, bytes memory operation) internal returns (bytes memory) {
76+
address precompile = address(0x0b);
77+
bytes memory input2 = abi.encodePacked(uint8(1), uint8(0), universal_address, operation);
78+
(bool success, bytes memory output) = precompile.call(input2);
79+
require(success);
80+
return output;
81+
}
82+
83+
function validation_round() internal returns (LineraTypes.opt_uint32 memory) {
84+
address precompile = address(0x0b);
85+
bytes memory input1 = new bytes(2);
86+
input1[0] = bytes1(uint8(1));
87+
input1[1] = bytes1(uint8(1));
88+
(bool success, bytes memory output1) = precompile.call(input1);
89+
require(success);
90+
LineraTypes.opt_uint32 memory val = LineraTypes.bcs_deserialize_opt_uint32(output1);
91+
return val;
92+
}
93+
94+
function send_message(bytes32 input_chain_id, bytes memory message) internal {
95+
address precompile = address(0x0b);
96+
bytes memory input2 = abi.encodePacked(uint8(1), uint8(2), input_chain_id, message);
97+
(bool success, bytes memory output) = precompile.call(input2);
98+
require(success);
99+
require(output.length == 0);
100+
}
101+
102+
function message_id() internal returns (LineraTypes.opt_MessageId memory) {
103+
address precompile = address(0x0b);
104+
bytes memory input1 = new bytes(2);
105+
input1[0] = bytes1(uint8(1));
106+
input1[1] = bytes1(uint8(3));
107+
(bool success, bytes memory output1) = precompile.call(input1);
108+
require(success);
109+
LineraTypes.opt_MessageId memory output2 = LineraTypes.bcs_deserialize_opt_MessageId(output1);
110+
return output2;
111+
}
112+
113+
function message_is_bouncing() internal returns (LineraTypes.MessageIsBouncing memory) {
114+
address precompile = address(0x0b);
115+
bytes memory input1 = new bytes(2);
116+
input1[0] = bytes1(uint8(1));
117+
input1[1] = bytes1(uint8(4));
118+
(bool success, bytes memory output1) = precompile.call(input1);
119+
require(success);
120+
LineraTypes.MessageIsBouncing memory output2 = abi.decode(output1, (LineraTypes.MessageIsBouncing));
121+
return output2;
122+
}
123+
124+
function try_query_application(bytes32 universal_address, bytes memory argument) internal returns (bytes memory) {
125+
address precompile = address(0x0b);
126+
bytes memory input2 = abi.encodePacked(uint8(2), uint8(0), universal_address, argument);
127+
(bool success, bytes memory output) = precompile.call(input2);
128+
require(success);
129+
return output;
130+
}
131+
}

0 commit comments

Comments
 (0)