Skip to content
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

Process finality proofs in solidity PoA -> Substrate contract #69

Merged
merged 102 commits into from
May 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
dbd7f0e
solidity contract
svyatonik Apr 3, 2020
a9d58a0
continue
svyatonik Apr 6, 2020
6995aac
upd
svyatonik Apr 6, 2020
7a55f48
cargo update
svyatonik Apr 6, 2020
f7e9768
fixes
svyatonik Apr 6, 2020
3a13d1f
ehtereum_headers -> headers
svyatonik Apr 6, 2020
39555d0
extracted some common stuff
svyatonik Apr 6, 2020
5831990
ethereum_sync.rs -> sync.rs
svyatonik Apr 6, 2020
4dfffd8
make sync generic
svyatonik Apr 7, 2020
33e9e31
continue extracting
svyatonik Apr 7, 2020
e132276
Merge branch 'master' into solidity-contract
svyatonik Apr 8, 2020
4ec3f6f
continue
svyatonik Apr 8, 2020
bf77451
add eth-contract argument
svyatonik Apr 8, 2020
1312d6e
continue
svyatonik Apr 9, 2020
cfc9235
some fixes
svyatonik Apr 9, 2020
b73aa54
contract v2
svyatonik Apr 10, 2020
f29b2e5
continue
svyatonik Apr 10, 2020
d90dff3
more fixes
svyatonik Apr 13, 2020
eb07871
Merge branch 'master' into solidity-contract
svyatonik Apr 13, 2020
ac393da
more fixes
svyatonik Apr 13, 2020
abebf1a
deal with duplicated params
svyatonik Apr 13, 2020
8168278
removed multiple call_rpc variants
svyatonik Apr 13, 2020
fd02e2f
bail_on_error!()
svyatonik Apr 13, 2020
e15bd1f
fn submit_ethereum_transaction
svyatonik Apr 13, 2020
4fd2cff
more fixes
svyatonik Apr 13, 2020
ea6cc8c
cargo fmt --all
svyatonik Apr 13, 2020
dbda454
fix
svyatonik Apr 13, 2020
74cd275
bail_on_arg_error!()
svyatonik Apr 13, 2020
84443a1
fix
svyatonik Apr 13, 2020
8118db6
fix
svyatonik Apr 13, 2020
c434b64
remove async_extra stuff
svyatonik Apr 15, 2020
0bc5743
start work on finality builtin
svyatonik Apr 15, 2020
89578fb
added TODO
svyatonik Apr 20, 2020
48928ec
substrate-bridge.json -> substrate-bridge-abi.json
svyatonik Apr 21, 2020
47c07cf
get rid of substrate transactions hashes
svyatonik Apr 21, 2020
ccc58b0
get rid of ethereum transactions hashes
svyatonik Apr 21, 2020
369afaa
extracted contract bytecode to separate file
svyatonik Apr 21, 2020
27505e3
cargo fmt --all
svyatonik Apr 21, 2020
c1daf3c
avoid duplicate import in contracts
svyatonik Apr 21, 2020
e560d1c
removed Default::default()
svyatonik Apr 22, 2020
7bcc95f
swapped configurations for sub2eth && eth2sub
svyatonik Apr 22, 2020
e37fb2b
fix compilation
svyatonik Apr 22, 2020
bdfaaf2
do not double gas limit when submitting Substrate headers
svyatonik Apr 22, 2020
ddb14c6
fix finality storage
svyatonik Apr 22, 2020
e3f8bac
at least 1 validator required
svyatonik Apr 22, 2020
e95fe30
shift_session_manager_works
svyatonik Apr 22, 2020
0ba79b1
cargo fmt --all
svyatonik Apr 22, 2020
5123adc
solidity contract removed
svyatonik Apr 23, 2020
d9efb22
consts
svyatonik Apr 23, 2020
16a06f8
extracted solc compilation details to separate file
svyatonik Apr 28, 2020
0911921
removed (obsolete in future Vec<u8> justification)
svyatonik Apr 28, 2020
da6f9b1
fixed cli option description
svyatonik Apr 28, 2020
427ef9b
fix typos
svyatonik Apr 28, 2020
bbdad9e
fix grumble
svyatonik Apr 28, 2020
d1f8bb0
extracted constants
svyatonik Apr 28, 2020
4615fc4
Merge branch 'master' into solidity-contract
svyatonik Apr 28, 2020
042d8fe
log decoded header
svyatonik Apr 28, 2020
b3d62b0
Merge branch 'solidity-contract' into solidity-contract-finality
svyatonik Apr 28, 2020
736c545
new substrate version + actually verify justification
svyatonik Apr 28, 2020
65e55cd
Merge branch 'master' into solidity-contract-finality
svyatonik Apr 28, 2020
daf3814
Merge branch 'master' into solidity-contract-finality
svyatonik Apr 29, 2020
a67f2aa
intermediate cargo fmt --all
svyatonik Apr 29, 2020
694ab99
comments
svyatonik Apr 29, 2020
d119221
disable completion data resubmission
svyatonik Apr 29, 2020
f5f1801
increased timeouts + _MS -> Duration
svyatonik Apr 29, 2020
d243ca4
forget completion data after submission
svyatonik May 1, 2020
d45fcff
builtin tests
svyatonik May 1, 2020
92d781d
headers tests
svyatonik May 1, 2020
295abdf
cargo fmt --all
svyatonik May 1, 2020
455e2fd
update contract
svyatonik May 1, 2020
cb76698
Update relays/ethereum/src/ethereum_sync_loop.rs
svyatonik May 5, 2020
9e19787
Update relays/ethereum/src/ethereum_sync_loop.rs
svyatonik May 5, 2020
0973137
added docs
svyatonik May 5, 2020
27809da
OwnedFutureOutput
svyatonik May 5, 2020
0b3789c
more docs fixes
svyatonik May 5, 2020
a187bef
cargo fmt --all
svyatonik May 5, 2020
5957571
Merge branch 'solidity-contract-finality' of https://github.com/parit…
svyatonik May 5, 2020
5913b01
encode headers
svyatonik May 5, 2020
d055941
consts + docs
svyatonik May 5, 2020
6d5a37c
aliases again
svyatonik May 5, 2020
585cd33
cargo fmt --all
svyatonik May 5, 2020
06c0fdf
Update relays/ethereum/src/ethereum_sync_loop.rs
HCastano May 6, 2020
acdf980
Update relays/ethereum/src/ethereum_sync_loop.rs
HCastano May 6, 2020
bd04d7f
Use Duration::from_secs() instead of from_millis()
HCastano May 6, 2020
d9bae15
grumbles
svyatonik May 6, 2020
89c5335
Merge branch 'master' into solidity-contract-finality
svyatonik May 6, 2020
085ff2f
Update relays/ethereum/src/headers.rs
tomusdrw May 6, 2020
a5a060c
Update relays/ethereum/src/headers.rs
tomusdrw May 6, 2020
a074d0e
incomplete_headers_are_still_incomplete_after_advance
svyatonik May 6, 2020
b80972d
add hex-encoded headers to substrate_header_without_signal_parsed
svyatonik May 6, 2020
5bb2e68
Merge branch 'solidity-contract-finality' of https://github.com/parit…
svyatonik May 6, 2020
79c8345
cargo fmt --all
svyatonik May 6, 2020
0798757
Update relays/ethereum/src/sync_loop.rs
svyatonik May 8, 2020
75e8c29
Update relays/ethereum/src/headers.rs
svyatonik May 11, 2020
77180d7
Update relays/ethereum/src/headers.rs
svyatonik May 11, 2020
23c254f
Update relays/ethereum/src/headers.rs
svyatonik May 11, 2020
8e62782
Update relays/ethereum/src/headers.rs
svyatonik May 11, 2020
83725c0
Update relays/ethereum/src/headers.rs
svyatonik May 11, 2020
2812db1
Update relays/ethereum/src/headers.rs
svyatonik May 11, 2020
16c4845
Update relays/ethereum/src/headers.rs
svyatonik May 11, 2020
a4f00cd
Merge branch 'master' into solidity-contract-finality
svyatonik May 11, 2020
16f1f29
added comments on Extra and Completion
svyatonik May 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,598 changes: 388 additions & 1,210 deletions Cargo.lock

Large diffs are not rendered by default.

33 changes: 29 additions & 4 deletions modules/ethereum-contract/builtin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,36 @@ edition = "2018"
# General dependencies

codec = { package = "parity-scale-codec", version = "1.0.0" }
finality-grandpa = { version = "0.12.2", features = ["derive-codec"] }
sp-blockchain = "2.0.0-alpha.5"
sp-finality-grandpa = "2.0.0-alpha.5"
sp-runtime = "2.0.0-alpha.5"
ethereum-types = "0.9.1"

# Runtime/chain specific dependencies

bridge-node-runtime = { path = "../../../bin/node/runtime" }

[dependencies.sp-blockchain]
version = "2.0.0-alpha.6"
rev = "c13ad41634d0bd7cf07897c2aa062b917d520520"
git = "https://github.com/paritytech/substrate/"

[dependencies.sp-finality-grandpa]
version = "2.0.0-alpha.6"
rev = "c13ad41634d0bd7cf07897c2aa062b917d520520"
git = "https://github.com/paritytech/substrate/"

[dependencies.sp-runtime]
version = "2.0.0-alpha.6"
rev = "c13ad41634d0bd7cf07897c2aa062b917d520520"
git = "https://github.com/paritytech/substrate/"

[dependencies.sc-finality-grandpa]
version = "0.8.0-dev"
rev = "c13ad41634d0bd7cf07897c2aa062b917d520520"
git = "https://github.com/paritytech/substrate/"

[dev-dependencies]
hex = "0.4"

[dev-dependencies.sp-core]
version = "2.0.0-alpha.6"
rev = "c13ad41634d0bd7cf07897c2aa062b917d520520"
git = "https://github.com/paritytech/substrate/"
271 changes: 256 additions & 15 deletions modules/ethereum-contract/builtin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,29 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.

use bridge_node_runtime::{BlockNumber, Hash, Header as RuntimeHeader};
use codec::Decode;
use bridge_node_runtime::{Block, BlockNumber, Hash, Header as RuntimeHeader};
use codec::{Decode, Encode};
use ethereum_types::U256;
use sp_blockchain::Error as ClientError;
use sp_finality_grandpa::{AuthorityList, ConsensusLog, GRANDPA_ENGINE_ID};

/// Builtin errors.
#[derive(Debug)]
pub enum Error {
/// Failed to decode block number.
BlockNumberDecode,
/// Failed to decode Substrate header.
HeaderDecode(codec::Error),
/// Failed to decode best voters set.
BestVotersDecode(codec::Error),
BestSetDecode(codec::Error),
/// Failed to decode finality proof.
FinalityProofDecode(codec::Error),
/// Failed to verify justification.
JustificationVerify(ClientError),
}

/// Substrate header.
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub struct Header {
/// Header hash.
pub hash: Hash,
Expand All @@ -45,35 +49,272 @@ pub struct Header {
}

/// GRANDPA validators set change signal.
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub struct ValidatorsSetSignal {
/// Signal delay.
pub delay: BlockNumber,
/// New validators set.
pub validators: Vec<u8>,
}

/// Convert from U256 to BlockNumber. Fails if `U256` value isn't fitting within `BlockNumber`
/// limits (the runtime referenced by this module uses u32 as `BlockNumber`).
pub fn to_substrate_block_number(number: U256) -> Result<BlockNumber, Error> {
match number == number.low_u32().into() {
true => Ok(number.low_u32()),
false => Err(Error::BlockNumberDecode),
}
}

/// Convert from BlockNumber to U256.
pub fn from_substrate_block_number(number: BlockNumber) -> Result<U256, Error> {
Ok(U256::from(number as u64))
}

/// Parse Substrate header.
pub fn parse_substrate_header(raw_header: &[u8]) -> Result<Header, Error> {
RuntimeHeader::decode(&mut &raw_header[..])
.map(|header| Header {
hash: header.hash(),
parent_hash: header.parent_hash,
number: header.number,
signal: None, // TODO: parse me
signal: sp_runtime::traits::Header::digest(&header)
.log(|log| {
log.as_consensus().and_then(|(engine_id, log)| {
if engine_id == GRANDPA_ENGINE_ID {
Some(log)
} else {
None
}
})
})
.and_then(|log| ConsensusLog::decode(&mut &log[..]).ok())
.and_then(|log| match log {
ConsensusLog::ScheduledChange(scheduled_change) => Some(ValidatorsSetSignal {
delay: scheduled_change.delay,
validators: scheduled_change.next_authorities.encode(),
}),
_ => None,
}),
})
.map_err(Error::HeaderDecode)
}

/// Verify GRANDPA finality proof.
pub fn verify_substrate_finality_proof(
_best_set_id: u64,
_raw_best_voters: &[u8],
_raw_best_header: &[u8],
_raw_headers: &[&[u8]],
_raw_finality_proof: &[u8],
) -> Result<(usize, usize), Error> {
Err(Error::JustificationVerify(ClientError::Msg(
"Not yet implemented".into(),
))) // TODO: implement me
finality_target_number: BlockNumber,
finality_target_hash: Hash,
best_set_id: u64,
raw_best_set: &[u8],
raw_finality_proof: &[u8],
) -> Result<(), Error> {
let best_set = AuthorityList::decode(&mut &raw_best_set[..]).map_err(Error::BestSetDecode)?;
sc_finality_grandpa::GrandpaJustification::<Block>::decode_and_verify_finalizes(
&raw_finality_proof,
(finality_target_hash, finality_target_number),
best_set_id,
&best_set.into_iter().collect(),
)
.map_err(Error::JustificationVerify)
.map(|_| ())
}

#[cfg(test)]
mod tests {
use super::*;
use bridge_node_runtime::DigestItem;
use sp_core::crypto::Public;
use sp_finality_grandpa::{AuthorityId, ScheduledChange};
use sp_runtime::generic::Digest;

#[test]
fn to_substrate_block_number_succeeds() {
assert_eq!(to_substrate_block_number(U256::zero()).unwrap(), 0);
assert_eq!(
to_substrate_block_number(U256::from(std::u32::MAX as u64)).unwrap(),
0xFFFFFFFF
);
}

#[test]
fn to_substrate_block_number_fails() {
assert!(matches!(
to_substrate_block_number(U256::from(std::u32::MAX as u64 + 1)),
Err(Error::BlockNumberDecode)
));
}

#[test]
fn from_substrate_block_number_succeeds() {
assert_eq!(from_substrate_block_number(0).unwrap(), U256::zero());
assert_eq!(
from_substrate_block_number(std::u32::MAX).unwrap(),
U256::from(std::u32::MAX)
);
}

#[test]
fn substrate_header_without_signal_parsed() {
let raw_header = RuntimeHeader {
parent_hash: [0u8; 32].into(),
number: 0,
state_root: "b2fc47904df5e355c6ab476d89fbc0733aeddbe302f0b94ba4eea9283f7e89e7"
.parse()
.unwrap(),
extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314"
.parse()
.unwrap(),
digest: Default::default(),
}
.encode();
assert_eq!(
raw_header,
hex::decode("000000000000000000000000000000000000000000000000000000000000000000b2fc47904df5e355c6ab476d89fbc0733aeddbe302f0b94ba4eea9283f7e89e703170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131400").unwrap(),
);

assert_eq!(
parse_substrate_header(&raw_header).unwrap(),
Header {
hash: "afbbeb92bf6ff14f60bdef0aa89f043dd403659ae82665238810ace0d761f6d0"
.parse()
.unwrap(),
parent_hash: Default::default(),
number: 0,
signal: None,
},
);
}

#[test]
fn substrate_header_with_signal_parsed() {
let authorities = vec![
(AuthorityId::from_slice(&[1; 32]), 101),
(AuthorityId::from_slice(&[3; 32]), 103),
];
let mut digest = Digest::default();
digest.push(DigestItem::Consensus(
GRANDPA_ENGINE_ID,
ConsensusLog::ScheduledChange(ScheduledChange {
next_authorities: authorities.clone(),
delay: 8,
})
.encode(),
));

let raw_header = RuntimeHeader {
parent_hash: "c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b"
.parse()
.unwrap(),
number: 8,
state_root: "822d6b412033aa9ac8e1722918eec5f25633529225754b3d4149982f5cacd4aa"
.parse()
.unwrap(),
extrinsics_root: "e7b07c0ce2799416ce7877b9cefc7f596bea5e8813bb2a0abf760414073ca928"
.parse()
.unwrap(),
digest,
}
.encode();
assert_eq!(
raw_header,
hex::decode("c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b20822d6b412033aa9ac8e1722918eec5f25633529225754b3d4149982f5cacd4aae7b07c0ce2799416ce7877b9cefc7f596bea5e8813bb2a0abf760414073ca928040446524e4b59010108010101010101010101010101010101010101010101010101010101010101010165000000000000000303030303030303030303030303030303030303030303030303030303030303670000000000000008000000").unwrap(),
);

assert_eq!(
parse_substrate_header(&raw_header).unwrap(),
Header {
hash: "3dfebb280bd87a4640f89d7f2adecd62b88148747bff5b63af6e1634ee37a56e"
.parse()
.unwrap(),
parent_hash: "c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b"
.parse()
.unwrap(),
number: 8,
signal: Some(ValidatorsSetSignal {
delay: 8,
validators: authorities.encode(),
}),
},
);
}

/// Number of the example block with justification.
const EXAMPLE_JUSTIFIED_BLOCK_NUMBER: u32 = 8;
/// Hash of the example block with justification.
const EXAMPLE_JUSTIFIED_BLOCK_HASH: &'static str =
"a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f343775";
/// Id of authorities set that have generated example justification. Could be computed by tracking
/// every set change in canonized headers.
const EXAMPLE_AUTHORITIES_SET_ID: u64 = 0;
/// Encoded authorities set that has generated example justification. Could be fetched from `ScheduledChange`
/// digest of the block that has scheduled this set OR by calling `GrandpaApi::grandpa_authorities()` at
/// appropriate block.
const EXAMPLE_AUTHORITIES_SET: &'static str = "1488dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0100000000000000d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae690100000000000000439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f01000000000000005e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d901000000000000001dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b50100000000000000";
/// Example justification. Could be fetched by calling 'chain_getBlock' RPC.
const EXAMPLE_JUSTIFICATION: &'static str = "2600000000000000a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000010a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000d66b4ceb57ef8bcbc955071b597c8c5d2adcfdbb009c73f8438d342670fdeca9ac60686cbd58105b10f51d0a64a8e73b2e5829b2eab3248a008c472852130b00439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234fa2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000f5730c14d3cd22b7661e2f5fcb3139dd5fef37f946314a441d01b40ce1200ef70d810525f23fd278b588cd67473c200bda83c338c407b479386aa83798e5970b5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000c78d6ec463f476461a695b4791d30e7626d16fdf72d7c252c2cad387495a97e8c2827ed4d5af853d6e05d31cb6fb7438c9481a7e9c6990d60a9bfaf6a6e1930988dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eea2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000052b4fc52d430286b3e2d650aa6e01b6ff4fae8b968893a62be789209eb97ee6e23780d3f5af7042d85bb48f1b202890b22724dfebce138826f66a5e00324320fd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae6900";

#[test]
fn substrate_header_parse_fails() {
assert!(matches!(parse_substrate_header(&[]), Err(_)));
}

#[test]
fn verify_substrate_finality_proof_succeeds() {
verify_substrate_finality_proof(
EXAMPLE_JUSTIFIED_BLOCK_NUMBER,
EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(),
EXAMPLE_AUTHORITIES_SET_ID,
&hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(),
&hex::decode(EXAMPLE_JUSTIFICATION).unwrap(),
)
.unwrap();
}

#[test]
fn verify_substrate_finality_proof_fails_when_wrong_block_is_finalized() {
verify_substrate_finality_proof(
4,
Default::default(),
EXAMPLE_AUTHORITIES_SET_ID,
&hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(),
&hex::decode(EXAMPLE_JUSTIFICATION).unwrap(),
)
.unwrap_err();
}

#[test]
fn verify_substrate_finality_proof_fails_when_wrong_set_is_provided() {
verify_substrate_finality_proof(
EXAMPLE_JUSTIFIED_BLOCK_NUMBER,
EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(),
EXAMPLE_AUTHORITIES_SET_ID,
&hex::decode("deadbeef").unwrap(),
&hex::decode(EXAMPLE_JUSTIFICATION).unwrap(),
)
.unwrap_err();
}

#[test]
fn verify_substrate_finality_proof_fails_when_wrong_set_id_is_provided() {
verify_substrate_finality_proof(
EXAMPLE_JUSTIFIED_BLOCK_NUMBER,
EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(),
42,
&hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(),
&hex::decode(EXAMPLE_JUSTIFICATION).unwrap(),
)
.unwrap_err();
}

#[test]
fn verify_substrate_finality_proof_fails_when_wrong_proof_is_provided() {
verify_substrate_finality_proof(
EXAMPLE_JUSTIFIED_BLOCK_NUMBER,
EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(),
0,
&hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(),
&hex::decode("deadbeef").unwrap(),
)
.unwrap_err();
}
}
19 changes: 9 additions & 10 deletions relays/ethereum/res/substrate-bridge-abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,18 @@
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "headerHash",
"type": "bytes32"
}
],
"name": "isFinalityProofRequired",
"inputs": [],
"name": "incompleteHeaders",
"outputs": [
{
"internalType": "bool",
"internalType": "uint256[]",
"name": "",
"type": "bool"
"type": "uint256[]"
},
{
"internalType": "bytes32[]",
"name": "",
"type": "bytes32[]"
}
],
"stateMutability": "view",
Expand Down
Loading