From 6245ee60187291c8614dfd564cc9a6d684dea0e5 Mon Sep 17 00:00:00 2001 From: Sophie Dankel <47993817+sdankel@users.noreply.github.com> Date: Tue, 19 Nov 2024 08:49:41 -0800 Subject: [PATCH] feat: add function for generating bytecode identifier (#6674) ## Description Depends on https://github.com/FuelLabs/sway/pull/6522 Related https://github.com/FuelLabs/forc.pub/issues/16 Adds a function, `get_bytecode_id` that generates a sha256 hash of the bytecode with the configurables section of the bytecode removed. This will be used for indexing and lookups of the corresponding ABIs for contracts, predicates, and scripts in the package registry (forc.pub). ## Checklist - [ ] I have linked to any relevant issues. - [ ] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [ ] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [ ] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: Vaivaswatha Nagaraj Co-authored-by: IGI-111 Co-authored-by: Marcos Henrich Co-authored-by: Joshua Batty --- Cargo.lock | 2 + forc-util/Cargo.toml | 2 + forc-util/src/bytecode.rs | 170 ++++++++++++++++++ forc-util/src/lib.rs | 1 + ...-configurable_constants-missing-offset.bin | Bin 0 -> 5328 bytes .../bytecode/debug-configurable_constants.bin | Bin 0 -> 5336 bytes .../tests/fixtures/bytecode/debug-counter.bin | Bin 0 -> 4488 bytes .../release-configurable_constants.bin | Bin 0 -> 4328 bytes .../fixtures/bytecode/release-counter.bin | Bin 0 -> 3456 bytes forc/src/cli/commands/parse_bytecode.rs | 14 +- 10 files changed, 177 insertions(+), 12 deletions(-) create mode 100644 forc-util/src/bytecode.rs create mode 100644 forc-util/tests/fixtures/bytecode/debug-configurable_constants-missing-offset.bin create mode 100644 forc-util/tests/fixtures/bytecode/debug-configurable_constants.bin create mode 100644 forc-util/tests/fixtures/bytecode/debug-counter.bin create mode 100644 forc-util/tests/fixtures/bytecode/release-configurable_constants.bin create mode 100644 forc-util/tests/fixtures/bytecode/release-counter.bin diff --git a/Cargo.lock b/Cargo.lock index 159d6d5f8cd..00233a2c23b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2958,6 +2958,7 @@ dependencies = [ "dirs 5.0.1", "fd-lock", "forc-tracing 0.66.4", + "fuel-asm", "fuel-tx", "hex", "paste", @@ -2965,6 +2966,7 @@ dependencies = [ "serde", "serde_json", "serial_test", + "sha2 0.10.8", "sway-core", "sway-error", "sway-types", diff --git a/forc-util/Cargo.toml b/forc-util/Cargo.toml index b2b5cdded43..a7bd7364a7f 100644 --- a/forc-util/Cargo.toml +++ b/forc-util/Cargo.toml @@ -16,6 +16,7 @@ clap = { workspace = true, features = ["cargo", "derive", "env"] } dirs.workspace = true fd-lock.workspace = true forc-tracing.workspace = true +fuel-asm.workspace = true fuel-tx = { workspace = true, optional = true } hex.workspace = true paste.workspace = true @@ -23,6 +24,7 @@ regex.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true serial_test.workspace = true +sha2.workspace = true sway-core.workspace = true sway-error.workspace = true sway-types.workspace = true diff --git a/forc-util/src/bytecode.rs b/forc-util/src/bytecode.rs new file mode 100644 index 00000000000..7bf71cc2302 --- /dev/null +++ b/forc-util/src/bytecode.rs @@ -0,0 +1,170 @@ +use anyhow::anyhow; +use sha2::{Digest, Sha256}; +use std::fs::File; +use std::io::{BufReader, Read}; +use std::path::Path; + +// The index of the beginning of the half-word (4 bytes) that contains the configurables section offset. +const CONFIGURABLES_OFFSET_INSTR_LO: usize = 4; +// The index of the end of the half-word (4 bytes) that contains the configurables section offset. +const CONFIGURABLES_OFFSET_INSTR_HI: usize = 5; +// The count of the beginning half-words that contain the configurables section offset. +const CONFIGURABLES_OFFSET_PREAMBLE: usize = CONFIGURABLES_OFFSET_INSTR_HI + 1; + +/// A tuple of an instruction and its corresponding bytes. Useful when needing to access the raw bytes +/// of an instruction that is parsed as [fuel_asm::InvalidOpcode], such as metadata in the preamble. +pub type InstructionWithBytes = ( + Result, + Vec, +); + +/// An iterator over each [fuel_asm::Instruction] or [fuel_asm::InvalidOpcode] with its corresponding bytes. +pub struct InstructionWithBytesIterator { + buf_reader: BufReader, +} + +impl InstructionWithBytesIterator { + /// Return a new iterator for each instruction parsed from raw bytes. + pub fn new(buf_reader: BufReader) -> Self { + InstructionWithBytesIterator { buf_reader } + } +} + +impl Iterator for InstructionWithBytesIterator { + type Item = InstructionWithBytes; + + fn next(&mut self) -> Option { + let mut buffer = [0; fuel_asm::Instruction::SIZE]; + // Read the next instruction into the buffer + match self.buf_reader.read_exact(&mut buffer) { + Ok(_) => fuel_asm::from_bytes(buffer) + .next() + .map(|inst| (inst, buffer.to_vec())), + Err(_) => None, + } + } +} + +/// Parses a bytecode file into an iterator of instructions and their corresponding bytes. +pub fn parse_bytecode_to_instructions

(path: P) -> anyhow::Result +where + P: AsRef + Clone, +{ + let f = File::open(path.clone()) + .map_err(|_| anyhow!("{}: file not found", path.as_ref().to_string_lossy()))?; + let buf_reader = BufReader::new(f); + + Ok(InstructionWithBytesIterator::new(buf_reader)) +} + +/// Gets the bytecode ID from a bytecode file. The bytecode ID is the hash of the bytecode after removing the +/// condigurables section, if any. +pub fn get_bytecode_id

(path: P) -> anyhow::Result +where + P: AsRef + Clone, +{ + let mut instructions = parse_bytecode_to_instructions(path.clone())?; + + // Collect the first six instructions into a temporary vector + let mut first_six_instructions = Vec::with_capacity(CONFIGURABLES_OFFSET_PREAMBLE); + for _ in 0..CONFIGURABLES_OFFSET_PREAMBLE { + if let Some(instruction) = instructions.next() { + first_six_instructions.push(instruction); + } else { + return Err(anyhow!("Incomplete bytecode")); + } + } + + let (lo_instr, low_raw) = &first_six_instructions[CONFIGURABLES_OFFSET_INSTR_LO]; + let (hi_instr, hi_raw) = &first_six_instructions[CONFIGURABLES_OFFSET_INSTR_HI]; + + if let Err(fuel_asm::InvalidOpcode) = lo_instr { + if let Err(fuel_asm::InvalidOpcode) = hi_instr { + // Now assemble the configurables offset. + let configurables_offset = usize::from_be_bytes([ + low_raw[0], low_raw[1], low_raw[2], low_raw[3], hi_raw[0], hi_raw[1], hi_raw[2], + hi_raw[3], + ]); + + // Hash the first six instructions + let mut hasher = Sha256::new(); + for (_, raw) in first_six_instructions { + hasher.update(raw); + } + + // Continue hashing the remaining instructions up to the configurables section offset. + instructions + .take( + configurables_offset / fuel_asm::Instruction::SIZE + - CONFIGURABLES_OFFSET_PREAMBLE, + ) // Minus 6 because we already hashed the first six + .for_each(|(_, raw)| { + hasher.update(raw); + }); + + let hash_result = hasher.finalize(); + let bytecode_id = format!("{:x}", hash_result); + return Ok(bytecode_id); + } + } + + Err(anyhow!("Configurables section offset not found")) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_get_bytecode_id_happy() { + let bytecode_id: String = + get_bytecode_id("tests/fixtures/bytecode/debug-counter.bin").expect("bytecode id"); + assert_eq!( + bytecode_id, + "e65aa988cae1041b64dc2d85e496eed0e8a1d8105133bd313c17645a1859d53b".to_string() + ); + + let bytecode_id = + get_bytecode_id("tests/fixtures/bytecode/release-counter.bin").expect("bytecode id"); + assert_eq!( + bytecode_id, + "42ae8352cbc892d7c7621f1d6fb42b072a08ba5968508d49f54991668d4ea141".to_string() + ); + + let bytecode_id = + get_bytecode_id("tests/fixtures/bytecode/debug-configurable_constants.bin") + .expect("bytecode id"); + assert_eq!( + bytecode_id, + "babc3d9dcac8d48dee1e5aeb3340ff098d3c1ab8b0a28341d9291d8ff757199e".to_string() + ); + + let bytecode_id = + get_bytecode_id("tests/fixtures/bytecode/release-configurable_constants.bin") + .expect("bytecode id"); + assert_eq!( + bytecode_id, + "2adfb515b66763fd29391bdba012921d045a0be83d89be5492bcaacc429695e9".to_string() + ); + } + + #[test] + fn test_get_bytecode_id_missing_configurable_offset() { + let result = get_bytecode_id( + "tests/fixtures/bytecode/debug-configurable_constants-missing-offset.bin", + ); + assert_eq!( + result.unwrap_err().to_string().as_str(), + "Configurables section offset not found" + ); + } + + #[test] + fn test_get_bytecode_id_bad_path() { + let result = get_bytecode_id("tests/fixtures/bytecode/blahblahblahblah.bin"); + assert_eq!( + result.unwrap_err().to_string().as_str(), + "tests/fixtures/bytecode/blahblahblahblah.bin: file not found" + ); + } +} diff --git a/forc-util/src/lib.rs b/forc-util/src/lib.rs index 003d50898ad..03775dcf8f1 100644 --- a/forc-util/src/lib.rs +++ b/forc-util/src/lib.rs @@ -23,6 +23,7 @@ use sway_error::{ use sway_types::{LineCol, LineColRange, SourceEngine, Span}; use sway_utils::constants; +pub mod bytecode; pub mod fs_locking; pub mod restricted; diff --git a/forc-util/tests/fixtures/bytecode/debug-configurable_constants-missing-offset.bin b/forc-util/tests/fixtures/bytecode/debug-configurable_constants-missing-offset.bin new file mode 100644 index 0000000000000000000000000000000000000000..cedfa0b99ae3d6b709335b707dfec5162b423aea GIT binary patch literal 5328 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

qE>n$ zw99;f-Ev@8hux%dYAUp2x%ZrbznM9lGhL0c&fJZY`7qJ#%P{YWeT3B!fnRCryNg|Gk8CJp`voteZ5zf_pR;&@1onJZUnb4z9U93_)JL+wIYqRZp;xf)y(9L$ z672iI5&OPwCN+n5kKo}X^KdRd@$%{v4FKP-FG(ULrL9sjrZSS$l)S8zJg2U2Hp+7p zv91kOl&zv#w#Qf&ceR{0D)V*;xmSGvUSgIXo0z$WeRO{G?PwV}jktdht{1O+7mKsrrK00~Uu1IywTv-?LX0~q`yOd7y9;IcF9uCW(NDA9*qk0kATbb{Wt0=xykjxabjE_ zhU>s}8MuB>OnO&fYly5-IRYCoHZ{FfFVEwg{8(Ms1&*zuW1ifO1MAzsx&W+q;E!r! z-Ck^Cy^kIPU)WE(ltAs$d=^|yS9g%BF|JwEU4rY$+)beNyJI`>d%vG}lRgfv)7plX z5x1g^{)%Vd4{);HQ=wkvw&I~3@TY)3jkx{@K1D@#^eFtT*t&jfKLp+z!246+y@@k? zjGF)L$u{2FP780cwgbGe_VfK1e4T4Q*XES7-Dp316)pR<(Bc#EdPAj!0G0;oW?tFx zC@`V+fHmpe^J@<^>C`0b(bsfN;JM0Y>F3_Q8~L|iGc^hBo?<`Y*O|w402|Jot;KL1 zoc;KWEjTZu4|Bk>t;mo_R=l&Jc=_dDS#9QaydbkemUkCT+vCjqggxvdb?vZ;B zfcHAi#C>%^*BSORfDgF0qlm|C#N$oG<1OT02hZC+cbdm`U5SNtxkB`>_lbV<=O}uK zz7I*7$qh1{bux1mGG`m;+tBUeF8avp>hW}*Ib+=L%TPDHxVcyAe&-VRc*G@&xJ1WO zh7@T-y6FVh4xUF_&u%j@Xcjc5sPzKZ`f;{HZdpEuj1w~V+^iwZ{}L?|z0~K-lR^K} zc`=?Z)J1-@?&gWaHN}{}@kavAXOiv#_g{ejji*H5;aJFn&jIk~8pQc-J^}t`@$mg) z!TVPazwdK(c-EkA@qNV{cCCMtdFiu0ZqD{yA7f1A0>w^e&&cBSeR>(ccowJg7yW1a zp2A%UuA-;&sd{l1@8mBMubr|dfB`t3i4eop0K;%Mh9dgWJnrKn^Oa9X*G|AT-f27B zZHw72b|`PAeJ=Xt4fwy&kv9>JaUUK|1Thr;UE&EdB`AzL;ukZYB|p)mD6LsYM z3HLF4-Rn6^`ty-Dd@CO(ZNoipwpzhH61joCmO?KJWZa2dN8nR+V16}-ZwqtCC+7y^ z;M~A{6&1*@KKapO56O z404aLnrR6R;#!`q$>I!pLpp`tp!>D3a#h_Uz-^-Ays*c#`YO&7VJ_*rxM@_(q^Iu? z?oY569eEh`*;bE&{d4r0$a@`e>Dy-zyQ?~1z~^)HnZd9Zgjo0v?CP(BK@EKs?2#j| ze-(Ru_7`w>5c&%4*89YI4Ka;bGh-5Y6SJE5pT$A`@hs}psOWkx6mNRRFsDSt3}*jp z>B?#$nEeZw{ckMDvvWNAFH3WtXaD73_V+SwbLqI-EPV|#$&1)CruX#owWMX_t3H!+ z^+}v#zuu8M2h5*?e$1Z(e98;UE9H0Hw|@2RouB_~rF{F%cNX6BwfuMZANcb*zW>Ab a0AGsmpN>!X91Ye)@Ox)v;T;yk_5TB0wCCvn literal 0 HcmV?d00001 diff --git a/forc-util/tests/fixtures/bytecode/release-counter.bin b/forc-util/tests/fixtures/bytecode/release-counter.bin new file mode 100644 index 0000000000000000000000000000000000000000..9f504b1c6876c0967d4336304e452a097a7fbd8b GIT binary patch literal 3456 zcmcImU1(cn7=F{8xOD66r%Sbd-RzmBT{irQTQ^n|cS0JHn1!6ujaek5I0x>+S%VwG zE*22P3&C!n?!t?RIC^!`|0%u%^v$f(*XS+GSwhE<2dCOJz=L7YLzTS;>l=L^JO>SThe@O@I4K_8$KWJ zOBrXnlonLVJJXdT6cM?YTW*=tcHX(c=XlP*S;&e-BHoG-c2R^YFV? zZdp;>g<;=-ov$DAWJg`lT56wGdTq5&#$351NZwu(N0;@UwdmDSs=Y-diTURt?_=2U z68!ANy3bD49bXRomwjN^0w&qYhKGYA%AN?KH^A+wES_%Zv^C51M=toM*f_Z z-ve3a4qDy*^}H!@H?sDA&j$BldAvat%b-#4NNW}~Ru{1K8NS2%Z22z5kQ)=RALM#N ztg^_{Ao6U%kEYtIoH>USjmnvG)2A;@IYXtQvjg?A6SNVLHmreM)IFP}5b8P%x}KrJ zSatLWQGDkFNqd$=a)Qc98}(M7LEfJ$w-V2zMqWT2*c~19OTG@|u+h0+Xut=q)4{lB z%iA3~XZ0TT4BKfT;Liu}^F=#pMi6`MDb%l14bgc@2TcaLge(GorqH8D5sS$I zV3gHOvs+FzXnWxR{t4uf=+bziqi}`f)q_FX9&Bm~Rlb{~GtHnGr&L1vrY|O^=i=Jo-pH?Mf9vw_3=>NS|fX0({qm}ygIMXsXh05st$}) z{cm#rqi-Up+g_GElrtE+B11X!Zx*$hoh7?icgJ%^0~q@V`e+9D(TAG%`U#kUp6|!K zUA`-}DBkp#CDJkE^xeE+<7O$PeCGzc*n^VtbM-=n5SqBAolZ{2{)}mY@G& zo&WQJ__tT<{*5Zh>Iq()kUG8SgQn_fU_(y!6ZhQmn zh|Xh8(HFmExwa=4{c>xKZ1sMC9VX}#$_~ye?~~A#s#o# z;g<64Z6as7Dj%&V>V*v81J5)wp2mF3I9b$TmT_loPlqh-X`TByxlDdd`MD3~#?*Qr z)q49`Z>iW8qL6U$Zhnm4&F~F9IAE>X!RPddrR~6etcq{j?40my%uTqceV)hJINl-M zZ__grI>k1cX<>oxrlQL)D!T6X9`bup$IuM;;?JA)e0f~^vR(TU)xHe;PriJ~zChh#0s)32N>p89^}y?xiNU5XdZ2IJvZ<=N1A?mBCg|;TVbxYG*drZ9!dTVH2uQk11((9bJ(yw~`S+76p_4=P# CXaaQr literal 0 HcmV?d00001 diff --git a/forc/src/cli/commands/parse_bytecode.rs b/forc/src/cli/commands/parse_bytecode.rs index 4d5ecf0bdb6..0ffa6f0ba4a 100644 --- a/forc/src/cli/commands/parse_bytecode.rs +++ b/forc/src/cli/commands/parse_bytecode.rs @@ -1,8 +1,6 @@ -use anyhow::anyhow; use clap::Parser; +use forc_util::bytecode::parse_bytecode_to_instructions; use forc_util::ForcResult; -use std::fs::{self, File}; -use std::io::Read; use term_table::row::Row; use term_table::table_cell::{Alignment, TableCell}; use tracing::info; @@ -21,15 +19,7 @@ pub(crate) struct Command { } pub(crate) fn exec(command: Command) -> ForcResult<()> { - let mut f = File::open(&command.file_path) - .map_err(|_| anyhow!("{}: file not found", command.file_path))?; - let metadata = fs::metadata(&command.file_path) - .map_err(|_| anyhow!("{}: file not found", command.file_path))?; - let mut buffer = vec![0; metadata.len() as usize]; - f.read_exact(&mut buffer).expect("buffer overflow"); - - let instructions = fuel_asm::from_bytes(buffer.iter().cloned()) - .zip(buffer.chunks(fuel_asm::Instruction::SIZE)); + let instructions = parse_bytecode_to_instructions(&command.file_path)?; let mut table = term_table::Table::new(); table.separate_rows = false;