chore: initial commit for v0.0.1
DChain single-node blockchain + React Native messenger client. Core: - PBFT consensus with multi-sig validator admission + equivocation slashing - BadgerDB + schema migration scaffold (CurrentSchemaVersion=0) - libp2p gossipsub (tx/v1, blocks/v1, relay/v1, version/v1) - Native Go contracts (username_registry) alongside WASM (wazero) - WebSocket gateway with topic-based fanout + Ed25519-nonce auth - Relay mailbox with NaCl envelope encryption (X25519 + Ed25519) - Prometheus /metrics, per-IP rate limit, body-size cap Deployment: - Single-node compose (deploy/single/) with Caddy TLS + optional Prometheus - 3-node dev compose (docker-compose.yml) with mocked internet topology - 3-validator prod compose (deploy/prod/) for federation - Auto-update from Gitea via /api/update-check + systemd timer - Build-time version injection (ldflags → node --version) - UI / Swagger toggle flags (DCHAIN_DISABLE_UI, DCHAIN_DISABLE_SWAGGER) Client (client-app/): - Expo / React Native / NativeWind - E2E NaCl encryption, typing indicator, contact requests - Auto-discovery of canonical contracts, chain_id aware, WS reconnect on node switch Documentation: - README.md, CHANGELOG.md, CONTEXT.md - deploy/single/README.md with 6 operator scenarios - deploy/UPDATE_STRATEGY.md with 4-layer forward-compat design - docs/contracts/*.md per contract
This commit is contained in:
102
contracts/counter/counter.wat
Normal file
102
contracts/counter/counter.wat
Normal file
@@ -0,0 +1,102 @@
|
||||
(module
|
||||
;; Counter smart contract — methods: increment, get, reset
|
||||
;; State key "counter" stores uint64 as 8-byte big-endian.
|
||||
;; State key "owner" stores the deployer pub key set on first reset() call.
|
||||
|
||||
;; ── imports ──────────────────────────────────────────────────────────────
|
||||
(import "env" "put_u64"
|
||||
(func $put_u64 (param i32 i32 i64)))
|
||||
(import "env" "get_u64"
|
||||
(func $get_u64 (param i32 i32) (result i64)))
|
||||
(import "env" "get_caller"
|
||||
(func $get_caller (param i32 i32) (result i32)))
|
||||
(import "env" "get_state"
|
||||
(func $get_state (param i32 i32 i32 i32) (result i32)))
|
||||
(import "env" "set_state"
|
||||
(func $set_state (param i32 i32 i32 i32)))
|
||||
(import "env" "log"
|
||||
(func $log (param i32 i32)))
|
||||
|
||||
;; ── memory ───────────────────────────────────────────────────────────────
|
||||
;; Memory layout:
|
||||
;; offset 0 : "counter" (7 bytes) — state key for the counter value
|
||||
;; offset 16 : "owner" (5 bytes) — state key for the owner pub key
|
||||
;; offset 32 : caller buffer (128 bytes)
|
||||
;; offset 160 : owner buffer (128 bytes)
|
||||
;; offset 288 : log messages
|
||||
(memory (export "memory") 1)
|
||||
|
||||
(data (i32.const 0) "counter")
|
||||
(data (i32.const 16) "owner")
|
||||
(data (i32.const 288) "incremented")
|
||||
(data (i32.const 300) "get called")
|
||||
(data (i32.const 310) "reset")
|
||||
(data (i32.const 316) "unauthorized")
|
||||
(data (i32.const 329) "reset ok")
|
||||
|
||||
;; ── increment() ──────────────────────────────────────────────────────────
|
||||
(func (export "increment")
|
||||
(local $val i64)
|
||||
(local.set $val (call $get_u64 (i32.const 0) (i32.const 7)))
|
||||
(local.set $val (i64.add (local.get $val) (i64.const 1)))
|
||||
(call $put_u64 (i32.const 0) (i32.const 7) (local.get $val))
|
||||
(call $log (i32.const 288) (i32.const 11))
|
||||
)
|
||||
|
||||
;; ── get() ─────────────────────────────────────────────────────────────────
|
||||
(func (export "get")
|
||||
(call $log (i32.const 300) (i32.const 10))
|
||||
)
|
||||
|
||||
;; ── reset() ───────────────────────────────────────────────────────────────
|
||||
;; Resets counter to 0. Only callable by the deployer (first caller sets ownership).
|
||||
(func (export "reset")
|
||||
(local $callerLen i32)
|
||||
(local $ownerLen i32)
|
||||
(local $i i32)
|
||||
(local $same i32)
|
||||
|
||||
(local.set $callerLen (call $get_caller (i32.const 32) (i32.const 128)))
|
||||
(local.set $ownerLen
|
||||
(call $get_state (i32.const 16) (i32.const 5) (i32.const 160) (i32.const 128)))
|
||||
|
||||
;; No owner yet — first caller becomes owner and resets to 0
|
||||
(if (i32.eqz (local.get $ownerLen))
|
||||
(then
|
||||
(call $set_state (i32.const 16) (i32.const 5) (i32.const 32) (local.get $callerLen))
|
||||
(call $put_u64 (i32.const 0) (i32.const 7) (i64.const 0))
|
||||
(call $log (i32.const 329) (i32.const 8))
|
||||
return
|
||||
)
|
||||
)
|
||||
|
||||
;; Length mismatch → unauthorized
|
||||
(if (i32.ne (local.get $callerLen) (local.get $ownerLen))
|
||||
(then (call $log (i32.const 316) (i32.const 12)) return)
|
||||
)
|
||||
|
||||
;; Byte-by-byte comparison
|
||||
(local.set $same (i32.const 1))
|
||||
(local.set $i (i32.const 0))
|
||||
(block $break
|
||||
(loop $loop
|
||||
(br_if $break (i32.ge_u (local.get $i) (local.get $callerLen)))
|
||||
(if (i32.ne
|
||||
(i32.load8_u (i32.add (i32.const 32) (local.get $i)))
|
||||
(i32.load8_u (i32.add (i32.const 160) (local.get $i))))
|
||||
(then (local.set $same (i32.const 0)) (br $break))
|
||||
)
|
||||
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
||||
(br $loop)
|
||||
)
|
||||
)
|
||||
|
||||
(if (i32.eqz (local.get $same))
|
||||
(then (call $log (i32.const 316) (i32.const 12)) return)
|
||||
)
|
||||
|
||||
;; Authorized — reset
|
||||
(call $put_u64 (i32.const 0) (i32.const 7) (i64.const 0))
|
||||
(call $log (i32.const 329) (i32.const 8))
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user