From 6d8906ebe98450d2f52b7dc9b53be30c3e5c1e0f Mon Sep 17 00:00:00 2001 From: Omar Abdulla Date: Wed, 12 Nov 2025 12:54:19 +0300 Subject: [PATCH] Upload code when initializing the driver --- Cargo.lock | 1 + assets/revive_metadata.scale | Bin 66887 -> 76558 bytes crates/core/Cargo.toml | 1 + .../src/differential_benchmarks/driver.rs | 19 +---- crates/core/src/differential_tests/driver.rs | 70 +++++++++++++----- crates/format/src/case.rs | 15 ++++ 6 files changed, 70 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f882991..91f6899 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5657,6 +5657,7 @@ dependencies = [ "semver 1.0.26", "serde", "serde_json", + "subxt 0.44.0", "tokio", "tracing", "tracing-appender", diff --git a/assets/revive_metadata.scale b/assets/revive_metadata.scale index 68c0a1e5409b50af47bcf1af6a441f59bd486dc3..461d07101643b2d25c22786dc2856cd248d3866b 100644 GIT binary patch delta 9479 zcmcgSZE#fAb@#rv#&SkZR`!CIuW$ttmO#h?OIS4GLqbXM!GTU`!Vel~ zdd_|O@t#%?yFbb-yQ_E4*FB&2+_QiCjPJYu;F}faw&uS*HR~6PXldrkqKkAj>t|#q|#IP|~TS@y22K%t}#7IiFqFL$k z=)yAv&}5p$wu@&rEgTrAVM)^%)jJe1^SXhgHRDD`h$)v%h-`k|OHgpWcfR^fS7 zL?0g3!>O1(UU=BVccWK@ayW&RDs(O_ghI|%XrN`>=4p%23M3rU!Po^*R?N&F)vRbe z^|wors$#~7Y2lp{u~#0X{$4DholT_E8b0lHH01syB;e0{W@miV856hsK|_Zo5TBlQGH zRSR+QVY&jyEsfnpFC{@oXFlTDKOq~Y>(ED5Ds(gIVcH5PgTNXgN`pcgfZ@aGX%K`2 zX_e!K9!INlo=x{(KW12W7Y&iR;_uoE{CIgaSBV|T02}D>f|F@csz?$PIf8uPOIQ}WG!l`+r7DhLI?@ah*Wr1 z-?#+fZ%GX|dkN#(*6fmKIytwR`bMXRG$g$75M(6Xm6S=dw3Ay#Hz`8uXpJTh1CWR< zyG@~0&GOGq_>0hXEoDayQ{SUu+LIt%3XP!~H@jC5x-DUwwtMEHG>9vJ4szM!GlMvJKJVBYXo+pOLn3G{vB#6V zgx2)IN1L8Rr4Skz)nciFP^1mRvO^&qphW$?F8phYLbjkv#fOu7>DD6ix*U}Fz2?QG zym|Y*=EXI)dBw7m4=SV|$**?X&JA~W+lhV0m!@Yhh1U{ATHox}dT}BDVn*3E?KCmX zD!Hz`7D?iy3S*C?MaJUo{2 zgx43353~dqADoz9UWf?XQnB*6_~FS)su!8Sl`p580GIM6hoBFzNKr*{Yw^oa9P(0; zlvLH7F$iIWoLyW~yb0rT`Q{99PNjQQmC!0oxXx~i^)ikbcCSMAN|CDyCq`7s0?j$s zd-AvzH&O{#`v3{ebE0X2jIKl9VVKj-I%FU6dP*TrDgOGT?7~9ON9&`!l#j;oxV0RP z{dnGL%(l1R&@4O+!!eT@`AJoC9zy??{AA9*34hi{WXrfJpm1t%ie>=H}gzii9WB)l+|t?I z-4*KX_`|kPOMhQm?*Q~`w$n~=%X8Xw)S-iJ_9?V;4jvA?DqBa$f$6HLL)GSXdFL&X zDq6aekGosjDp{mMPW>)PK?_%(RaQu@xM2g(7KL|yO6yRlZE1Le?id?4r;Unh)=uj= zg)&@Dt;CkD$~K`9o@qe}Ji|h}ybFndf5`?Hn`uVUP5wMv_AcaGNA}#{+!ISPnY@b?d|LCY5qoA=Cx-(`-*Z* z5$E-Q_{#9Cdn!7$J>z1|@VYIN*-oZAsXER($w!^}u@`HJnw7^l%nfK*#hWa1l`g-Q0`5HhKY2 zO1gLY$cqI2mA09tk6dtYE{M>fcKW_JacD99vH0N7T=*V3v{>AG_!sauek(oFO)rWa zM=I&h#Gf2l2Jfej1cM&}I>9&PV}-zr_)2EeMsi7fe5B{Wi_lniB=A-)VYk8s2O*aw zsmLp<>#lgDyQa9syM{!)@?DdNS6_LHUKcOFTG@2Nql=rxy0{56Ko|I-+*Sy@K(s~* z&9EwNy}C@fM-`!?i^by;apgYe>qiq0EBC9ycXZ{l`&D-%T&5Ojx=fYS%MkNB%4}8q z@@Ta(R}~MuR&n1#SW|vV%2l!cwF;$D6%)r+DAlU?>9Hmn zYT%#KUQ~*?#vwR#Y^}1^5vSQBPTO6@0a)#gCfva*Zf*&hku6?xPV8G%QFEe# zR*Nks%HiEQu?*gioOozXF+%QWw_`xfUti(X2;@4a-6=vLT^`SXo^bjd3HC+ccU#a2 zW-A1w$!Xx;H|Hq*VE;Gg@P3unXRpiTRSX!t-$NLhz3GI37!n@vz-h&!qHRfm0eP_bcLA=%Zg#uwVLBSsl-MjF|3dHf?aUuldx$W z6!rG}HCo7k>v$9HYf~z1%x=K}#P$~M7P&dfBjYNq$}Uz_!{$;Rq3hgx8Sl2ldH>cpa3Ri<$k70{1(Z z@1Ks)1L7y|REceG&8N=^^Q}kdOXBETORAsqNPDo@5(gbZ2PO8Lx7Sy{r?h{VFVUET>ErE`m z>8o_z8U&4$?Y&0`fGG_V($-g}7-p{xQ$ac<`llAoJqrPWg?}TI%1&dX5D?-orsmTh zi8rT~mQA5-r&V$mKi^Zydy?sw-g#`Hiz!PQmW~%BeyHh>u7ctup}zA@J3SBITImI` zDN`xdWXj~XcKxH%EtxR8>#%i_#y!w&X&yW|sDIcl?URd2A zhNTS3C6&Mn9-RWYE_+NnS!`M`9a`p!#|bCVdAG%LUWhO`FN{0z*F5mo5&lLF{JIPL zh69d|d?i6Yxq(T0zIgiVa^8Ml-)0; z&TSHZeXi*X{;y6~ETnQY6i%5~?h8{HdCrGH4b0MDgyS3tnVyiNn?blZ8`cxhhwR~l z3?_k5BT`EiuqEsX!{#uvlfxev&ZS~7AL48{Wx~YAWCn~H;(!wYLbidV(y(TyaPDSg z2XICL26#9hg4u^2PsKq#JcpZcd0)p8oa4|5z@bqv5|(YI!p^iWrxoT%o}B^qY~JWh z|7yuv%6fH}l}PFikPZVupaLU79XAhDquMBEnh7mfqz0ywzzIZ=vmO?KiKhZ0|345nq(rOz`6s3gwLB zvwFwW;1{0Gtb3S}m%uN4D=Cu;Bgomx_H9530x=9@endY;XwMRq;B5)CeS`&_ zRZKPz(+~-?jS_l-RAnyy>pohuqm|2&w3(Y5qj1g8XX?De=JDVL@_fUX+rAYm#ko%! z(qV)GQo0jrP&=3o@U>(O`kw(R#{I!Y0! z&~Ou(fBa=P#YVg8N+X<1v@7R)XBFR{3+=NxV&!Kw^gZ$I&;AXLBQ3xB2^=RLxOx#f z)K9O*zjREIQ~!&~C9(b5e+DiqCH8L3Gbp^03H`@;g`| z55Dm0D0Foh`kU)iovU8Y+_>>=RavNJw%%M%(>p34+??Sz)XdT+Sr3QO0|^Kfo3DR; z?M^OTa3}oRznNzgymV}FP@L;}%7IJaEWN)Rc4ZRzxAY_HG z0fzxAX(S?`99gFsln>K@2^H=a(vOoG3)v$9$y-ca4P*}f_j>9tSF7agOUl~_t@NkA zod}kz@^H6Cb$;35x3rkuL7}ldd~5qX9V%D-;`XftOP_}<0>3y3%V30`Xt2T2Rf7zY zm4&|xf_i}&s#eUsUAt@$Rg;q;gwuDt5`q*{0)Eq>W;4nzAT4g)deT>}?p4K;xBpam z3OwY0Iw*d2{%#9Z52zCdU!}i;&&w|yrS!L@dE5i)l@}%z8mFheA5`gSO0T`}H$M7D I>P?mWFMtNBwg3PC delta 2660 zcmaJ@eN0=|6~E^^Lrr5+JK@7%oIC?2n1mFPCWQ@}(!vzFP{LO=hY|V;kKhJ>U_Wmq zQkrB_yJcGFva{)>f3#UNRcfZD9doFYP#`2D2_$qwT_#l%nrN3v*_O4a${*>}cK6!U z!?85!>fY=7&iS3+J?GqWJp5|jnZ?N@-gC5^LxySF*f=Z7jt1qZMVa?{I1%h|iI)b{#j-=Pji)+g3*{i#!P*=U|a0kHn{1)d1p;ml7Ey`|0o=T-#{#= zBIAS8s`4Q7ApPZhndC(i9e&wHMHfQS;PU?Lg>nodeSD#EV>k(aC>4Jwjz6@lx@YWp zJcx8<%!Nmgmd1)RUJ{o7$c`edd#@OeAswD5$Ky!vOf=!ENMBAA%C8|j8;@E|>n6G0 z6ACC=Pd^WpKlm79T=wupKCK(i$6q3SV_X)?cgG*4qLUVSWx_^MCnp*~ceq#1&qgbZkD8Wcc(-!>8{v z%-9GyhOP9oU#zCjCW~+s$$HTRQxy2QOwU~`!x^OEi@DZ$o+|O2uj$ybZTn*k%zZ(> z_a=>Bv~ExRSiDaObq9i;9yRq_md6(eYab%5nkt5Qs+e-{xpk_H&j+V+b5a$In*Sz! z@~W+K@qZ+q7}8WuBI|p~KseO~8%;`)^QkFvKAs|C!Et2c2`BuRp3ImMr_;!$6Q`fk z!HgMkI)`kIpW12qSdJh(ya8^~o)b>^Fd_S`OF6iJwD(d@?*hUj%U%H$x?&=PgB}pqgRVzELm7UOf z`)cRfJbs9FiSfZpk=Y?JN8)?^HFJSeg5oE6+u=31M-+N_cTf#!ipGn5H3hC^fiod~ z=32Xxhczn}a0XU?SmWuw;v`EIMTA$Pk{Q`{1fgmO-RxZ{`Npy#0x2~Ce6z1ruS)1q+%V)#0J9)2&|JuYm z#i8rYHT+Wbp1!^&f3Io;Qy{2{JsSxzP>L0maPpEY+AlucZiTVKp-^?U*c}SLQatAdStPh3rV+{WpuDAd>glIfD@zfWezgj{X4P2TS8u&pTptJQtQgI)d)#NFMB!@Fk2|?63o1 zSM<_)zM79>X{=ax3!_!XP`5bXl=Uda!gvZ}T&m0=Wk73$H&CB-Kxf(r-bRyNRtN?9 zVj*-Jj^bU^>xAJYh0 i`Jcf)&%QKC(FaSxi#IX)*HSnGpz6oU;6-UrV*dpRxBMpn diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 63c8275..2b0f76f 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -37,6 +37,7 @@ schemars = { workspace = true } semver = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +subxt = { workspace = true } [lints] workspace = true diff --git a/crates/core/src/differential_benchmarks/driver.rs b/crates/core/src/differential_benchmarks/driver.rs index 1d13b69..5dcc2fb 100644 --- a/crates/core/src/differential_benchmarks/driver.rs +++ b/crates/core/src/differential_benchmarks/driver.rs @@ -127,6 +127,8 @@ where .inspect_err(|err| error!(?err, "Pre-linking compilation failed")) .context("Failed to produce the pre-linking compiled contracts")?; + let deployer_address = self.test_definition.case.deployer_address(); + let mut deployed_libraries = None::>; let mut contract_sources = self .test_definition @@ -159,23 +161,6 @@ where let code = alloy::hex::decode(code)?; - // Getting the deployer address from the cases themselves. This is to ensure - // that we're doing the deployments from different accounts and therefore we're - // not slowed down by the nonce. - let deployer_address = self - .test_definition - .case - .steps - .iter() - .filter_map(|step| match step { - Step::FunctionCall(input) => input.caller.as_address().copied(), - Step::BalanceAssertion(..) => None, - Step::StorageEmptyAssertion(..) => None, - Step::Repeat(..) => None, - Step::AllocateAccount(..) => None, - }) - .next() - .unwrap_or(FunctionCallStep::default_caller_address()); let tx = TransactionBuilder::::with_deploy_code( TransactionRequest::default().from(deployer_address), code, diff --git a/crates/core/src/differential_tests/driver.rs b/crates/core/src/differential_tests/driver.rs index cffc74d..d7fdcef 100644 --- a/crates/core/src/differential_tests/driver.rs +++ b/crates/core/src/differential_tests/driver.rs @@ -8,7 +8,7 @@ use alloy::{ hex, json_abi::JsonAbi, network::{Ethereum, TransactionBuilder}, - primitives::{Address, TxHash, U256}, + primitives::{Address, TxHash, U256, address}, rpc::types::{ TransactionReceipt, TransactionRequest, trace::geth::{ @@ -18,9 +18,9 @@ use alloy::{ }, }; use anyhow::{Context as _, Result, bail}; -use futures::TryStreamExt; +use futures::{TryStreamExt, future::try_join_all}; use indexmap::IndexMap; -use revive_dt_common::types::{PlatformIdentifier, PrivateKeyAllocator}; +use revive_dt_common::types::{PlatformIdentifier, PrivateKeyAllocator, VmIdentifier}; use revive_dt_format::{ metadata::{ContractInstance, ContractPathAndIdent}, steps::{ @@ -30,6 +30,7 @@ use revive_dt_format::{ }, traits::ResolutionContext, }; +use subxt::{ext::codec::Decode, metadata::Metadata, tx::Payload}; use tokio::sync::Mutex; use tracing::{error, info, instrument}; @@ -198,6 +199,8 @@ where }) .context("Failed to produce the pre-linking compiled contracts")?; + let deployer_address = test_definition.case.deployer_address(); + let mut deployed_libraries = None::>; let mut contract_sources = test_definition .metadata @@ -232,22 +235,6 @@ where let code = alloy::hex::decode(code)?; - // Getting the deployer address from the cases themselves. This is to ensure - // that we're doing the deployments from different accounts and therefore we're - // not slowed down by the nonce. - let deployer_address = test_definition - .case - .steps - .iter() - .filter_map(|step| match step { - Step::FunctionCall(input) => input.caller.as_address().copied(), - Step::BalanceAssertion(..) => None, - Step::StorageEmptyAssertion(..) => None, - Step::Repeat(..) => None, - Step::AllocateAccount(..) => None, - }) - .next() - .unwrap_or(FunctionCallStep::default_caller_address()); let tx = TransactionBuilder::::with_deploy_code( TransactionRequest::default().from(deployer_address), code, @@ -295,6 +282,51 @@ where }) .context("Failed to compile the post-link contracts")?; + // Factory contracts on the PVM refer to the code that they're instantiating by hash rather + // than including the actual bytecode. This creates a problem where a factory contract could + // be deployed but the code it's supposed to create is not on chain. Therefore, we upload + // all the code to the chain prior to running any transactions on the driver. + if platform_information.platform.vm_identifier() == VmIdentifier::PolkaVM { + #[subxt::subxt(runtime_metadata_path = "../../assets/revive_metadata.scale")] + pub mod revive {} + + let metadata_bytes = include_bytes!("../../../../assets/revive_metadata.scale"); + let metadata = Metadata::decode(&mut &metadata_bytes[..]) + .context("Failed to decode the revive metadata")?; + + const RUNTIME_PALLET_ADDRESS: Address = + address!("0x6d6f646c70792f70616464720000000000000000"); + + let code_upload_tasks = compiler_output + .contracts + .values() + .flat_map(|item| item.values()) + .map(|(code_string, _)| { + let metadata = metadata.clone(); + async move { + let code = alloy::hex::decode(code_string) + .context("Failed to hex-decode the post-link code. This is a bug")?; + let payload = revive::tx().revive().upload_code(code, u128::MAX); + let encoded_payload = payload + .encode_call_data(&metadata) + .context("Failed to encode the upload code payload")?; + + let tx_request = TransactionRequest::default() + .from(deployer_address) + .to(RUNTIME_PALLET_ADDRESS) + .input(encoded_payload.into()); + platform_information + .node + .execute_transaction(tx_request) + .await + .context("Failed to execute transaction") + } + }); + try_join_all(code_upload_tasks) + .await + .context("Code upload failed")?; + } + Ok(ExecutionState::new( compiler_output.contracts, deployed_libraries.unwrap_or_default(), diff --git a/crates/format/src/case.rs b/crates/format/src/case.rs index 44639dd..19114a9 100644 --- a/crates/format/src/case.rs +++ b/crates/format/src/case.rs @@ -1,3 +1,4 @@ +use alloy::primitives::Address; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -107,6 +108,20 @@ impl Case { None => Mode::all().cloned().collect(), } } + + pub fn deployer_address(&self) -> Address { + self.steps + .iter() + .filter_map(|step| match step { + Step::FunctionCall(input) => input.caller.as_address().copied(), + Step::BalanceAssertion(..) => None, + Step::StorageEmptyAssertion(..) => None, + Step::Repeat(..) => None, + Step::AllocateAccount(..) => None, + }) + .next() + .unwrap_or(FunctionCallStep::default_caller_address()) + } } define_wrapper_type!(