forked from Haroldwonder/TrustLink
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
346 lines (310 loc) · 16.3 KB
/
Copy pathMakefile
File metadata and controls
346 lines (310 loc) · 16.3 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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
.PHONY: build test optimize clean install help local-deploy check-size
# ─────────────────────────────────────────────────────────────────────────────
# TrustLink Makefile
# ─────────────────────────────────────────────────────────────────────────────
#
# Network targeting
# -----------------
# NETWORK — target network name (default: testnet)
# Recognised values: testnet | mainnet | local
#
# The three networks are pre-configured with their canonical RPC URLs and
# network passphrases. You can override any URL via environment variables:
#
# TESTNET_RPC_URL (default: https://soroban-testnet.stellar.org)
# MAINNET_RPC_URL (default: https://mainnet.stellar.validationcloud.io/v1/...)
# LOCAL_RPC_URL (default: http://localhost:8000/soroban/rpc)
#
# Signing identity
# ----------------
# ADMIN_SECRET — Stellar secret key (S...) used to sign deploy/invoke txns.
# Required for deploy and invoke targets.
# Never hard-code this value; pass it via the environment:
# export ADMIN_SECRET=SXXX...
# make deploy
#
# Contract ID
# -----------
# CONTRACT_ID — Required for invoke target. Set after a successful deploy:
# export CONTRACT_ID=C...
# make invoke ARGS="-- get_admin"
#
# ─────────────────────────────────────────────────────────────────────────────
NETWORK ?= testnet
WASM = target/wasm32-unknown-unknown/release/trustlink.wasm
WASM_OPT = target/wasm32-unknown-unknown/release/trustlink.optimized.wasm
WASM_SIZE_LIMIT ?= 102400
WASM_LOOKUP_DIR ?= target/wasm32-unknown-unknown/release
SHA256SUM ?= $(shell command -v sha256sum 2>/dev/null || command -v shasum 2>/dev/null)
SHA256SUM_ARGS ?= $(if $(filter shasum,$(notdir $(SHA256SUM))),-a 256,)
# ── RPC URLs (overridable via environment) ────────────────────────────────────
TESTNET_RPC_URL ?= https://soroban-testnet.stellar.org
MAINNET_RPC_URL ?= https://mainnet.stellar.validationcloud.io/v1/wI7lMGrm7ZU5UP9jKa7R3A
LOCAL_RPC_URL ?= http://localhost:8000/soroban/rpc
# ── Network passphrases ───────────────────────────────────────────────────────
TESTNET_PASSPHRASE = Test SDF Network ; September 2015
MAINNET_PASSPHRASE = Public Global Stellar Network ; September 2015
LOCAL_PASSPHRASE = Standalone Network ; February 2017
# ── Resolve active network settings ──────────────────────────────────────────
ifeq ($(NETWORK),mainnet)
RPC_URL = $(MAINNET_RPC_URL)
PASSPHRASE = $(MAINNET_PASSPHRASE)
else ifeq ($(NETWORK),local)
RPC_URL = $(LOCAL_RPC_URL)
PASSPHRASE = $(LOCAL_PASSPHRASE)
else
# Default: testnet
NETWORK = testnet
RPC_URL = $(TESTNET_RPC_URL)
PASSPHRASE = $(TESTNET_PASSPHRASE)
endif
.PHONY: build test snapshot-update optimize clean install fmt clippy deny \
deploy invoke \
testnet mainnet local \
bindings check-bindings \
check-size check-wasm-size check-error-variants rollback \
indexer-dev indexer-build indexer-logs \
changelog-preview test-changelog-preview \
help
# ─────────────────────────────────────────────────────────────────────────────
# Help
# ─────────────────────────────────────────────────────────────────────────────
help:
@echo "TrustLink Smart Contract - Makefile Commands"
@echo "============================================="
@echo "make build - Build the contract in debug mode"
@echo "make test - Run all unit tests"
@echo "make snapshot-update - Regenerate test_snapshots/ after intentional behaviour changes"
@echo "make optimize - Build release WASM and run wasm-opt -Oz"
@echo "make check-size - Verify optimized WASM is under 100 KB (alias for check-wasm-size)"
@echo "make check-wasm-size - Verify optimized WASM is under WASM_SIZE_LIMIT (default: 100 KB)"
@echo " Override: make check-wasm-size WASM_SIZE_LIMIT=<bytes>"
@echo "make clean - Clean build artifacts"
@echo "make fmt - Format source code"
@echo "make clippy - Run clippy linter"
@echo "make deny - Run cargo-deny (licenses, advisories, bans, sources)"
@echo "make install - Install required dependencies"
@echo "make local-deploy - Deploy and initialize contract on local Stellar network"
@echo "make rollback - Redeploy a verified WASM hash to a specified network"
@echo "make bindings - Generate TypeScript bindings from compiled WASM"
@echo "make check-bindings - Fail if committed bindings are out of date"
@echo "make check-error-variants - Fail if Error::Variant refs in src/ are undefined"
@echo "make deploy - Build, optimize, and deploy to NETWORK (default: testnet)"
@echo " Requires: ADMIN_SECRET=<secret> SOURCE=<key-alias>"
@echo " Example: make deploy NETWORK=testnet SOURCE=deployer"
@echo "make verify - Run post-deployment verification against a live contract"
@echo " Requires: CONTRACT_ID=<id> SOURCE=<key-alias>"
@echo " Optional: NETWORK=testnet|mainnet (default: testnet)"
@echo " Example: make verify CONTRACT_ID=C... SOURCE=deployer NETWORK=testnet"
@echo "make indexer-dev - Start the indexer stack (db + indexer) via docker compose"
@echo "make indexer-build - Build the indexer Docker image"
@echo "make indexer-logs - Tail logs from the running indexer container"
@echo "make changelog-preview - Preview the next version and changelog entry Release Please"
@echo " would generate, without creating a PR or modifying any files."
@echo " Example: make changelog-preview"
# ─────────────────────────────────────────────────────────────────────────────
# Build & test
# ─────────────────────────────────────────────────────────────────────────────
install:
@echo "Required dependencies:"
@echo " Rust: https://rustup.rs/"
@echo " Stellar CLI: cargo install --locked stellar-cli --features opt"
@echo " WASM target: rustup target add wasm32-unknown-unknown"
@echo " wasm-opt: cargo install --locked wasm-opt (or: apt install binaryen)"
## Build the contract in debug mode
build:
@echo "Building TrustLink ($(NETWORK))..."
cargo build --target wasm32-unknown-unknown --release
## Run all unit tests
test:
@echo "Running tests..."
cargo test
## Regenerate all snapshot files in test_snapshots/.
## Use this after intentional contract behaviour changes to accept new snapshots.
## Review the diff with: git diff test_snapshots/
## See docs/snapshot-testing.md for the full workflow.
snapshot-update:
@echo "Regenerating snapshots..."
cargo test
@echo "Snapshots updated. Review changes with: git diff test_snapshots/"
## Build release WASM, then run wasm-opt -Oz for maximum size reduction.
## Typical reduction: ~30–50% vs the raw release binary.
## Output: $(WASM_OPT)
optimize: build
@echo "Optimizing WASM with wasm-opt -Oz..."
wasm-opt -Oz --enable-bulk-memory --strip-debug \
$(WASM) -o $(WASM_OPT)
@echo "--- Size report ---"
@printf " Before: %d bytes (%d KB)\n" \
$$(stat -c%s $(WASM)) $$(( $$(stat -c%s $(WASM)) / 1024 ))
@printf " After: %d bytes (%d KB)\n" \
$$(stat -c%s $(WASM_OPT)) $$(( $$(stat -c%s $(WASM_OPT)) / 1024 ))
@printf " Saved: %d bytes\n" \
$$(( $$(stat -c%s $(WASM)) - $$(stat -c%s $(WASM_OPT)) ))
@echo "Optimized artifact: $(WASM_OPT)"
## Verify the optimized WASM binary is under the configurable size limit.
## Default limit: 100 KB. Override: make check-wasm-size WASM_SIZE_LIMIT=<bytes>
check-wasm-size: optimize
@SIZE=$$(stat -c%s $(WASM_OPT)); \
MAX=$(WASM_SIZE_LIMIT); \
echo "Optimized WASM size: $${SIZE} bytes ($$(( SIZE / 1024 )) KB) / limit $$(( MAX / 1024 )) KB ($(WASM_SIZE_LIMIT) bytes)"; \
if [ "$$SIZE" -gt "$$MAX" ]; then \
echo "ERROR: $(WASM_OPT) is $${SIZE} bytes — exceeds limit of $(WASM_SIZE_LIMIT) bytes ($$(( MAX / 1024 )) KB)."; \
exit 1; \
fi; \
echo "OK: binary is within the $(WASM_SIZE_LIMIT)-byte limit."
## Backwards-compatible alias for check-wasm-size
check-size: check-wasm-size
## Roll back to a previously built WASM hash and redeploy it to a selected network.
rollback:
@if [ -z "$(WASM_HASH)" ]; then \
echo "ERROR: WASM_HASH is required. Example: make rollback NETWORK=mainnet WASM_HASH=<hash>"; \
exit 1; \
fi; \
@if [ -z "$(SHA256SUM)" ]; then \
echo "ERROR: sha256sum or shasum is required to verify WASM hashes."; \
exit 1; \
fi; \
@echo "Searching for a matching WASM artifact in $(WASM_LOOKUP_DIR)..."; \
WASM_FILE=""; \
for f in $$(find $(WASM_LOOKUP_DIR) -type f -name '*.wasm' 2>/dev/null); do \
HASH=$$($(SHA256SUM) $(SHA256SUM_ARGS) "$$f" | awk '{print $$1}'); \
if [ "$$HASH" = "$(WASM_HASH)" ]; then \
WASM_FILE="$$f"; break; \
fi; \
done; \
if [ -z "$$WASM_FILE" ]; then \
echo "ERROR: no compiled WASM artifact found matching hash $(WASM_HASH)."; \
echo "Restore or build the matching WASM artifact and retry."; \
exit 1; \
fi; \
@if [ "$(NETWORK)" = "mainnet" ]; then \
echo "WARNING: mainnet rollback is sensitive. This will redeploy WASM hash $(WASM_HASH) to mainnet."; \
printf "Type 'ROLLBACK' to confirm: "; \
read CONFIRM; \
if [ "$$CONFIRM" != "ROLLBACK" ]; then \
echo "Aborted rollback."; \
exit 1; \
fi; \
fi; \
@echo "Rolling back with artifact: $$WASM_FILE"; \
soroban contract deploy --wasm "$$WASM_FILE" --network $(NETWORK)
## Clean build artifacts and compiled outputs
clean:
@echo "Cleaning build artifacts..."
cargo clean
## Format code according to Rust standards
fmt:
@echo "Formatting code..."
cargo fmt
## Run clippy linter and enforce strict warnings
clippy:
@echo "Running clippy..."
cargo clippy --all-targets -- -D warnings
## Run cargo-deny to check licenses, advisories, bans, and sources.
## Requires: cargo install --locked cargo-deny
deny:
@echo "Running cargo-deny checks..."
cargo deny check
local-deploy: build
@echo "Deploying TrustLink contract to local Stellar network..."
./scripts/setup_local.sh
## Generate TypeScript bindings from the compiled WASM
bindings: build
@echo "Generating TypeScript bindings..."
stellar contract bindings typescript \
--wasm $(WASM) \
--contract-id 0000000000000000000000000000000000000000000000000000000000000001 \
--network testnet \
--output-dir bindings/typescript
@echo "Bindings written to bindings/typescript/"
## Fail if committed bindings are out of date with the current WASM
check-bindings: bindings
@echo "Checking bindings are up to date..."
git diff --exit-code bindings/typescript/ || \
(echo "ERROR: TypeScript bindings are out of date. Run 'make bindings' and commit the result." && exit 1)
## Fail if any Error::Variant reference in src/ is missing from src/errors.rs
check-error-variants:
python3 scripts/check_error_variants.py
# ── Signing key alias (used by deploy and verify) ─────────────────────────────
# SOURCE is the stellar key alias (not the raw secret) passed to stellar CLI.
# For deploy, ADMIN_SECRET must also be exported so the CLI can sign.
SOURCE ?= deployer
## Build, optimize, and deploy the contract to NETWORK.
## Requires: ADMIN_SECRET exported in the environment; SOURCE set to a key alias.
## After deploy, note the printed CONTRACT_ID and run: make verify CONTRACT_ID=... SOURCE=...
deploy: optimize
ifeq ($(NETWORK),mainnet)
@echo "⚠ WARNING: Deploying to MAINNET. Press Ctrl-C within 5 seconds to abort."
@sleep 5
endif
@echo "Deploying TrustLink to $(NETWORK)..."
stellar contract deploy \
--wasm $(WASM_OPT) \
--source $(SOURCE) \
--network $(NETWORK)
@echo ""
@echo "════════════════════════════════════════════════════════════════"
@echo " Deployment complete."
@echo " ⚠ Run post-deployment verification before considering this done:"
@echo " make verify CONTRACT_ID=<printed-above> SOURCE=$(SOURCE) NETWORK=$(NETWORK)"
@echo "════════════════════════════════════════════════════════════════"
## Invoke any contract function on NETWORK.
## Usage: make invoke ARGS="-- <function> [--param value ...]"
invoke:
@test -n "$(CONTRACT_ID)" || (echo "Error: CONTRACT_ID is required. Export it or pass CONTRACT_ID=C..."; exit 1)
stellar contract invoke \
--id $(CONTRACT_ID) \
--source $(SOURCE) \
--network $(NETWORK) \
$(ARGS)
testnet:
$(MAKE) deploy NETWORK=testnet
mainnet:
$(MAKE) deploy NETWORK=mainnet
local:
$(MAKE) deploy NETWORK=local
## Run post-deployment verification against a live TrustLink contract.
## Executes scripts/verify_deployment.sh which creates a temporary issuer,
## issues a test attestation, verifies it, revokes it, and cleans up.
##
## Required: CONTRACT_ID=<contract-id> SOURCE=<stellar-key-alias>
## Optional: NETWORK=testnet|mainnet (default: testnet)
##
## Example:
## make verify CONTRACT_ID=CABC...XYZ SOURCE=deployer NETWORK=testnet
verify:
@test -n "$(CONTRACT_ID)" || (echo "Error: CONTRACT_ID is required. Usage: make verify CONTRACT_ID=C... SOURCE=<alias> [NETWORK=testnet|mainnet]"; exit 1)
@test -n "$(SOURCE)" || (echo "Error: SOURCE is required. Usage: make verify CONTRACT_ID=C... SOURCE=<alias> [NETWORK=testnet|mainnet]"; exit 1)
@echo "Running deployment verification for $(CONTRACT_ID) on $(NETWORK)..."
bash scripts/verify_deployment.sh \
--contract $(CONTRACT_ID) \
--source $(SOURCE) \
--network $(NETWORK)
# ─────────────────────────────────────────────────────────────────────────────
# Indexer
# ─────────────────────────────────────────────────────────────────────────────
## Start the indexer stack (db + indexer) in the foreground.
## Press Ctrl-C to stop. Requires CONTRACT_ID and RPC_URL to be set.
## Example:
## CONTRACT_ID=C... RPC_URL=https://soroban-testnet.stellar.org make indexer-dev
indexer-dev:
docker compose -f indexer/docker-compose.yml up
## Build the indexer Docker image without starting any containers.
indexer-build:
docker compose -f indexer/docker-compose.yml build indexer
## Tail logs from the running indexer container.
## Follows output until interrupted with Ctrl-C.
indexer-logs:
docker compose -f indexer/docker-compose.yml logs -f indexer
## Preview the next version and changelog entry that Release Please would generate.
## Parses conventional commits since the last release tag and prints the expected
## version bump and formatted changelog section without modifying any files.
##
## Example:
## make changelog-preview
changelog-preview:
@bash scripts/changelog-preview.sh
## Run automated tests for the changelog-preview script.
test-changelog-preview:
@bash tests/test_changelog_preview.sh