forked from Pi-Defi-world/acbu-smart-contract
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.rs
More file actions
181 lines (161 loc) · 6.63 KB
/
Copy pathbuild.rs
File metadata and controls
181 lines (161 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Build script for ACBU Smart Contracts
// Verifies WASM artifact integrity before compilation.
// Fails fast if hash mismatches to prevent supply chain attacks.
//
// The WASM file is NOT stored in git — only its SHA-256 hash is pinned
// in source (inside each contractimport! macro and in this script).
// Run ./scripts/fetch_token_wasm.sh to download the artifact before
// your first build.
use std::fs;
use std::path::Path;
use std::process;
/// Expected SHA-256 of soroban_token_contract.wasm.
/// Must match the sha256 field in every contractimport! that references
/// this artifact (acbu_minting, acbu_burning, acbu_reserve_tracker).
const EXPECTED_HASH: &str =
"6b14997b915dee21082884cd5a2f1f2f0aef0073d1dcb9c5b3c674cf487fb41d";
const WASM_PATH: &str = "soroban_token_contract.wasm";
fn main() {
// Re-run this script only when the WASM file itself changes.
println!("cargo:rerun-if-changed={}", WASM_PATH);
if !Path::new(WASM_PATH).exists() {
eprintln!("error[build]: {} not found.", WASM_PATH);
eprintln!();
eprintln!(" The WASM artifact is not stored in the repository.");
eprintln!(" Run the fetch script to download it before building:");
eprintln!();
eprintln!(" ./scripts/fetch_token_wasm.sh");
eprintln!();
eprintln!(" Expected SHA-256: {}", EXPECTED_HASH);
process::exit(1);
}
let data = fs::read(WASM_PATH).unwrap_or_else(|e| {
eprintln!("error[build]: Cannot read {}: {}", WASM_PATH, e);
process::exit(1);
});
let actual_hash = sha256_hex(&data);
if actual_hash != EXPECTED_HASH {
eprintln!("error[build]: WASM hash mismatch — possible supply-chain tampering.");
eprintln!(" expected: {}", EXPECTED_HASH);
eprintln!(" actual: {}", actual_hash);
eprintln!();
eprintln!(" Re-run ./scripts/fetch_token_wasm.sh to restore the verified artifact.");
process::exit(1);
}
println!(
"cargo:warning=soroban_token_contract.wasm verified ({} bytes, sha256 OK)",
data.len()
);
verify_source_hashes();
}
/// Verify that every contractimport! in source still references the expected hash.
fn verify_source_hashes() {
let tagged_files = [
"acbu_minting/src/lib.rs",
"acbu_burning/src/lib.rs",
"acbu_reserve_tracker/src/lib.rs",
];
for path in &tagged_files {
println!("cargo:rerun-if-changed={}", path);
match fs::read_to_string(path) {
Ok(content) => {
if content.contains("contractimport!")
&& !content.contains(&format!("sha256 = \"{}\"", EXPECTED_HASH))
{
eprintln!(
"error[build]: {} contains a contractimport! \
with a hash that does not match EXPECTED_HASH.",
path
);
eprintln!(" expected: {}", EXPECTED_HASH);
eprintln!(" Update the sha256 field in that file to match.");
process::exit(1);
}
}
Err(e) => {
eprintln!("cargo:warning=Could not read {} for hash check: {}", path, e);
}
}
}
}
/// Compute a lowercase hex SHA-256 digest without any external crate.
fn sha256_hex(data: &[u8]) -> String {
// Initial hash values (first 32 bits of fractional parts of square roots
// of the first 8 primes).
let mut h: [u32; 8] = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
];
// Round constants (first 32 bits of the fractional parts of the cube
// roots of the first 64 primes).
#[rustfmt::skip]
const K: [u32; 64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
];
// Pre-processing: pad message to 512-bit blocks.
let bit_len = (data.len() as u64).wrapping_mul(8);
let mut msg = data.to_vec();
msg.push(0x80);
while (msg.len() % 64) != 56 {
msg.push(0x00);
}
msg.extend_from_slice(&bit_len.to_be_bytes());
for block in msg.chunks(64) {
let mut w = [0u32; 64];
for (i, chunk) in block.chunks(4).enumerate().take(16) {
w[i] = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
}
for i in 16..64 {
let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
w[i] = w[i - 16]
.wrapping_add(s0)
.wrapping_add(w[i - 7])
.wrapping_add(s1);
}
let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] =
[h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]];
for i in 0..64 {
let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
let ch = (e & f) ^ ((!e) & g);
let temp1 = hh
.wrapping_add(s1)
.wrapping_add(ch)
.wrapping_add(K[i])
.wrapping_add(w[i]);
let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
let maj = (a & b) ^ (a & c) ^ (b & c);
let temp2 = s0.wrapping_add(maj);
hh = g; g = f; f = e;
e = d.wrapping_add(temp1);
d = c; c = b; b = a;
a = temp1.wrapping_add(temp2);
}
h[0] = h[0].wrapping_add(a);
h[1] = h[1].wrapping_add(b);
h[2] = h[2].wrapping_add(c);
h[3] = h[3].wrapping_add(d);
h[4] = h[4].wrapping_add(e);
h[5] = h[5].wrapping_add(f);
h[6] = h[6].wrapping_add(g);
h[7] = h[7].wrapping_add(hh);
}
h.iter()
.map(|v| format!("{:08x}", v))
.collect::<String>()
}