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:
538
contracts/governance/gen/main.go
Normal file
538
contracts/governance/gen/main.go
Normal file
@@ -0,0 +1,538 @@
|
||||
// gen generates contracts/governance/governance.wasm
|
||||
// Run from repo root: go run ./contracts/governance/gen/
|
||||
//
|
||||
// Methods: init, propose, approve, reject, get, get_pending, set_admin
|
||||
//
|
||||
// State layout (all keys are raw UTF-8 strings):
|
||||
// "admin" → admin address bytes
|
||||
// "param:<key>" → current live value bytes
|
||||
// "prop:<key>" → pending proposed value bytes
|
||||
//
|
||||
// Access control:
|
||||
// approve / reject / set_admin → admin only
|
||||
// propose / get / get_pending → anyone
|
||||
// init → anyone (but only writes if admin not set)
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ── LEB128 ───────────────────────────────────────────────────────────────────
|
||||
|
||||
func u(v uint64) []byte {
|
||||
var b []byte
|
||||
for {
|
||||
bt := byte(v & 0x7f)
|
||||
v >>= 7
|
||||
if v != 0 {
|
||||
bt |= 0x80
|
||||
}
|
||||
b = append(b, bt)
|
||||
if v == 0 {
|
||||
return b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func s(v int64) []byte {
|
||||
var b []byte
|
||||
for {
|
||||
bt := byte(v & 0x7f)
|
||||
v >>= 7
|
||||
sign := (bt & 0x40) != 0
|
||||
if (v == 0 && !sign) || (v == -1 && sign) {
|
||||
return append(b, bt)
|
||||
}
|
||||
b = append(b, bt|0x80)
|
||||
}
|
||||
}
|
||||
|
||||
func cat(slices ...[]byte) []byte {
|
||||
var out []byte
|
||||
for _, sl := range slices {
|
||||
out = append(out, sl...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func wstr(str string) []byte { return cat(u(uint64(len(str))), []byte(str)) }
|
||||
|
||||
func section(id byte, content []byte) []byte {
|
||||
return cat([]byte{id}, u(uint64(len(content))), content)
|
||||
}
|
||||
|
||||
func vec(items ...[]byte) []byte {
|
||||
out := u(uint64(len(items)))
|
||||
for _, it := range items {
|
||||
out = append(out, it...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func functype(params, results []byte) []byte {
|
||||
return cat([]byte{0x60}, u(uint64(len(params))), params, u(uint64(len(results))), results)
|
||||
}
|
||||
|
||||
func importFunc(mod, name string, typeIdx uint32) []byte {
|
||||
return cat(wstr(mod), wstr(name), []byte{0x00}, u(uint64(typeIdx)))
|
||||
}
|
||||
|
||||
func exportEntry(name string, kind byte, idx uint32) []byte {
|
||||
return cat(wstr(name), []byte{kind}, u(uint64(idx)))
|
||||
}
|
||||
|
||||
func dataSegment(offset int32, data []byte) []byte {
|
||||
return cat(
|
||||
[]byte{0x00},
|
||||
[]byte{0x41}, s(int64(offset)), []byte{0x0B},
|
||||
u(uint64(len(data))), data,
|
||||
)
|
||||
}
|
||||
|
||||
func funcBody(localDecls []byte, instrs ...[]byte) []byte {
|
||||
inner := cat(localDecls)
|
||||
for _, ins := range instrs {
|
||||
inner = append(inner, ins...)
|
||||
}
|
||||
inner = append(inner, 0x0B)
|
||||
return cat(u(uint64(len(inner))), inner)
|
||||
}
|
||||
|
||||
var noLocals = u(0)
|
||||
|
||||
func localDecl(n uint32, typ byte) []byte { return cat(u(uint64(n)), []byte{typ}) }
|
||||
func withLocals(decls ...[]byte) []byte {
|
||||
return cat(u(uint64(len(decls))), cat(decls...))
|
||||
}
|
||||
|
||||
const (
|
||||
tI32 byte = 0x7F
|
||||
tI64 byte = 0x7E
|
||||
)
|
||||
|
||||
func call(fn uint32) []byte { return cat([]byte{0x10}, u(uint64(fn))) }
|
||||
func lget(i uint32) []byte { return cat([]byte{0x20}, u(uint64(i))) }
|
||||
func lset(i uint32) []byte { return cat([]byte{0x21}, u(uint64(i))) }
|
||||
func ic32(v int32) []byte { return cat([]byte{0x41}, s(int64(v))) }
|
||||
func block_() []byte { return []byte{0x02, 0x40} }
|
||||
func loop_() []byte { return []byte{0x03, 0x40} }
|
||||
func if_() []byte { return []byte{0x04, 0x40} }
|
||||
func ifI32() []byte { return []byte{0x04, tI32} }
|
||||
func else_() []byte { return []byte{0x05} }
|
||||
func end_() []byte { return []byte{0x0B} }
|
||||
func br_(lbl uint32) []byte { return cat([]byte{0x0C}, u(uint64(lbl))) }
|
||||
func brIf_(lbl uint32) []byte { return cat([]byte{0x0D}, u(uint64(lbl))) }
|
||||
func return_() []byte { return []byte{0x0F} }
|
||||
func i32Eqz() []byte { return []byte{0x45} }
|
||||
func i32Ne() []byte { return []byte{0x47} }
|
||||
func i32GtU() []byte { return []byte{0x4B} }
|
||||
func i32GeU() []byte { return []byte{0x4F} }
|
||||
func i32Add() []byte { return []byte{0x6A} }
|
||||
func i32Load8U() []byte { return []byte{0x2D, 0x00, 0x00} }
|
||||
func i32Store8() []byte { return []byte{0x3A, 0x00, 0x00} }
|
||||
|
||||
// ── Memory layout ─────────────────────────────────────────────────────────────
|
||||
//
|
||||
// 0x000 64 arg[0] key buffer
|
||||
// 0x040 256 arg[1] value buffer
|
||||
// 0x140 128 caller buffer
|
||||
// 0x1C0 128 admin state-read buffer
|
||||
// 0x240 256 value state-read buffer
|
||||
// 0x340 256 scratch (build_key writes here, log_prefix_name writes here)
|
||||
//
|
||||
// Constant strings:
|
||||
// 0x500 6 "admin" (state key)
|
||||
// 0x506 6 "param:" (state key prefix)
|
||||
// 0x50D 5 "prop:" (state key prefix)
|
||||
// 0x513 13 "initialized: "
|
||||
// 0x521 9 "proposed: "
|
||||
// 0x52B 10 "approved: "
|
||||
// 0x536 10 "rejected: "
|
||||
// 0x541 8 "value: "
|
||||
// 0x549 11 "not set: "
|
||||
// 0x555 9 "pending: "
|
||||
// 0x55F 12 "no pending: "
|
||||
// 0x56C 7 "admin: "
|
||||
// 0x574 14 "unauthorized: "
|
||||
// 0x583 14 "already init: "
|
||||
|
||||
const (
|
||||
offArg0 int32 = 0x000
|
||||
offArg1 int32 = 0x040
|
||||
offCaller int32 = 0x140
|
||||
offAdminRead int32 = 0x1C0
|
||||
offValRead int32 = 0x240
|
||||
offScratch int32 = 0x340
|
||||
|
||||
offKeyAdmin int32 = 0x500 // "admin" 5 bytes
|
||||
offPfxParam int32 = 0x506 // "param:" 6 bytes
|
||||
offPfxProp int32 = 0x50D // "prop:" 5 bytes
|
||||
offInitedPfx int32 = 0x513 // "initialized: " 14
|
||||
offProposedPfx int32 = 0x521 // "proposed: " 9 (key=val shown as arg0=arg1)
|
||||
offApprovedPfx int32 = 0x52B // "approved: " 10
|
||||
offRejectedPfx int32 = 0x536 // "rejected: " 10
|
||||
offValuePfx int32 = 0x541 // "value: " 7
|
||||
offNotSetPfx int32 = 0x549 // "not set: " 9
|
||||
offPendingPfx int32 = 0x555 // "pending: " 9
|
||||
offNoPendingPfx int32 = 0x55F // "no pending: " 12
|
||||
offAdminPfx int32 = 0x56C // "admin: " 7
|
||||
offUnauthPfx int32 = 0x574 // "unauthorized: " 14
|
||||
offAlreadyPfx int32 = 0x583 // "already init" 12
|
||||
)
|
||||
|
||||
const (
|
||||
fnGetArgStr = 0
|
||||
fnGetCaller = 1
|
||||
fnGetState = 2
|
||||
fnSetState = 3
|
||||
fnLog = 4
|
||||
|
||||
fnBytesEqual = 5
|
||||
fnMemcpy = 6
|
||||
fnLogPrefixName = 7
|
||||
fnBuildKey = 8
|
||||
fnInit = 9
|
||||
fnPropose = 10
|
||||
fnApprove = 11
|
||||
fnReject = 12
|
||||
fnGet = 13
|
||||
fnGetPending = 14
|
||||
fnSetAdmin = 15
|
||||
)
|
||||
|
||||
// ── Helper bodies ─────────────────────────────────────────────────────────────
|
||||
|
||||
func bytesEqualBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(2, tI32)),
|
||||
ic32(1), lset(4), ic32(0), lset(3),
|
||||
block_(), loop_(),
|
||||
lget(3), lget(2), i32GeU(), brIf_(1),
|
||||
lget(0), lget(3), i32Add(), i32Load8U(),
|
||||
lget(1), lget(3), i32Add(), i32Load8U(),
|
||||
i32Ne(), if_(), ic32(0), lset(4), br_(2), end_(),
|
||||
lget(3), ic32(1), i32Add(), lset(3),
|
||||
br_(0), end_(), end_(),
|
||||
lget(4),
|
||||
)
|
||||
}
|
||||
|
||||
func memcpyBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(1, tI32)),
|
||||
ic32(0), lset(3),
|
||||
block_(), loop_(),
|
||||
lget(3), lget(2), i32GeU(), brIf_(1),
|
||||
lget(0), lget(3), i32Add(),
|
||||
lget(1), lget(3), i32Add(), i32Load8U(),
|
||||
i32Store8(),
|
||||
lget(3), ic32(1), i32Add(), lset(3),
|
||||
br_(0), end_(), end_(),
|
||||
)
|
||||
}
|
||||
|
||||
func logPrefixNameBody() []byte {
|
||||
return funcBody(
|
||||
noLocals,
|
||||
ic32(offScratch), lget(0), lget(1), call(fnMemcpy),
|
||||
ic32(offScratch), lget(1), i32Add(), lget(2), lget(3), call(fnMemcpy),
|
||||
ic32(offScratch), lget(1), lget(3), i32Add(), call(fnLog),
|
||||
)
|
||||
}
|
||||
|
||||
// $build_key(pfxOff, pfxLen, dataOff, dataLen i32) → keyLen i32
|
||||
func buildKeyBody() []byte {
|
||||
return funcBody(
|
||||
noLocals,
|
||||
ic32(offScratch), lget(0), lget(1), call(fnMemcpy),
|
||||
ic32(offScratch), lget(1), i32Add(), lget(2), lget(3), call(fnMemcpy),
|
||||
lget(1), lget(3), i32Add(),
|
||||
)
|
||||
}
|
||||
|
||||
// isCallerAdmin: reads admin from state into offAdminRead, returns 1 if caller==admin.
|
||||
// (callerLenLocal i32) → i32
|
||||
// Leaves adminLen on stack as side effect (stored in local adminLenLocal).
|
||||
// Emits code that: reads admin, compares with caller.
|
||||
// Uses offAdminRead for the state read buffer.
|
||||
func isCallerAdminCode(callerLenLocal, adminLenLocal uint32) []byte {
|
||||
return cat(
|
||||
// adminLen = get_state("admin", 5, offAdminRead, 128)
|
||||
ic32(offKeyAdmin), ic32(5), ic32(offAdminRead), ic32(128), call(fnGetState), lset(adminLenLocal),
|
||||
// if adminLen == 0: not initialized → return 0
|
||||
lget(adminLenLocal), i32Eqz(),
|
||||
ifI32(),
|
||||
ic32(0),
|
||||
else_(),
|
||||
// bytes_equal(offCaller, offAdminRead, callerLen) if callerLen==adminLen else 0
|
||||
lget(callerLenLocal), lget(adminLenLocal), i32Ne(),
|
||||
ifI32(), ic32(0), else_(),
|
||||
ic32(offCaller), ic32(offAdminRead), lget(callerLenLocal), call(fnBytesEqual),
|
||||
end_(),
|
||||
end_(),
|
||||
)
|
||||
}
|
||||
|
||||
// ── Contract method bodies ────────────────────────────────────────────────────
|
||||
|
||||
// init() — set caller as admin (only if not already initialized)
|
||||
func initBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(2, tI32)),
|
||||
// callerLen = get_caller(offCaller, 128)
|
||||
ic32(offCaller), ic32(128), call(fnGetCaller), lset(0),
|
||||
// Check if admin already set
|
||||
ic32(offKeyAdmin), ic32(5), ic32(offAdminRead), ic32(128), call(fnGetState), lset(1),
|
||||
lget(1), ic32(0), i32GtU(), if_(),
|
||||
ic32(offAlreadyPfx), ic32(12), ic32(offCaller), lget(0), call(fnLogPrefixName),
|
||||
return_(),
|
||||
end_(),
|
||||
// set state["admin"] = caller
|
||||
ic32(offKeyAdmin), ic32(5), ic32(offCaller), lget(0), call(fnSetState),
|
||||
ic32(offInitedPfx), ic32(14), ic32(offCaller), lget(0), call(fnLogPrefixName),
|
||||
)
|
||||
}
|
||||
|
||||
// propose(key, value) — store pending proposal
|
||||
// Locals: keyLen(0), valLen(1), keyBufLen(2)
|
||||
func proposeBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(3, tI32)),
|
||||
ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0),
|
||||
lget(0), i32Eqz(), if_(), return_(), end_(),
|
||||
ic32(1), ic32(offArg1), ic32(256), call(fnGetArgStr), lset(1),
|
||||
lget(1), i32Eqz(), if_(), return_(), end_(),
|
||||
|
||||
// set state["prop:<key>"] = value
|
||||
ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(2),
|
||||
ic32(offScratch), lget(2), ic32(offArg1), lget(1), call(fnSetState),
|
||||
|
||||
// log "proposed: <key>"
|
||||
ic32(offProposedPfx), ic32(9), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
)
|
||||
}
|
||||
|
||||
// approve(key) — admin: move prop:<key> → param:<key>
|
||||
// Locals: keyLen(0), callerLen(1), adminLen(2), propLen(3), keyBufLen(4)
|
||||
func approveBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(5, tI32)),
|
||||
ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0),
|
||||
lget(0), i32Eqz(), if_(), return_(), end_(),
|
||||
|
||||
ic32(offCaller), ic32(128), call(fnGetCaller), lset(1),
|
||||
isCallerAdminCode(1, 2),
|
||||
i32Eqz(), if_(),
|
||||
ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
return_(),
|
||||
end_(),
|
||||
|
||||
// Read pending value: get_state("prop:<key>", offValRead, 256)
|
||||
ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4),
|
||||
ic32(offScratch), lget(4), ic32(offValRead), ic32(256), call(fnGetState), lset(3),
|
||||
lget(3), i32Eqz(), if_(),
|
||||
ic32(offNoPendingPfx), ic32(12), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
return_(),
|
||||
end_(),
|
||||
|
||||
// set state["param:<key>"] = offValRead[0..propLen)
|
||||
ic32(offPfxParam), ic32(6), ic32(offArg0), lget(0), call(fnBuildKey), lset(4),
|
||||
ic32(offScratch), lget(4), ic32(offValRead), lget(3), call(fnSetState),
|
||||
|
||||
// delete pending: set state["prop:<key>"] = ""
|
||||
ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4),
|
||||
ic32(offScratch), lget(4), ic32(offScratch), ic32(0), call(fnSetState),
|
||||
|
||||
ic32(offApprovedPfx), ic32(10), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
)
|
||||
}
|
||||
|
||||
// reject(key) — admin: delete prop:<key>
|
||||
// Locals: keyLen(0), callerLen(1), adminLen(2), keyBufLen(3)
|
||||
func rejectBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(4, tI32)),
|
||||
ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0),
|
||||
lget(0), i32Eqz(), if_(), return_(), end_(),
|
||||
|
||||
ic32(offCaller), ic32(128), call(fnGetCaller), lset(1),
|
||||
isCallerAdminCode(1, 2),
|
||||
i32Eqz(), if_(),
|
||||
ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
return_(),
|
||||
end_(),
|
||||
|
||||
// delete pending
|
||||
ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(3),
|
||||
ic32(offScratch), lget(3), ic32(offScratch), ic32(0), call(fnSetState),
|
||||
ic32(offRejectedPfx), ic32(10), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
)
|
||||
}
|
||||
|
||||
// get(key) — read live parameter value
|
||||
// Locals: keyLen(0), valLen(1), keyBufLen(2)
|
||||
func getBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(3, tI32)),
|
||||
ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0),
|
||||
lget(0), i32Eqz(), if_(), return_(), end_(),
|
||||
|
||||
ic32(offPfxParam), ic32(6), ic32(offArg0), lget(0), call(fnBuildKey), lset(2),
|
||||
ic32(offScratch), lget(2), ic32(offValRead), ic32(256), call(fnGetState), lset(1),
|
||||
lget(1), i32Eqz(), if_(),
|
||||
ic32(offNotSetPfx), ic32(9), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
return_(),
|
||||
end_(),
|
||||
ic32(offValuePfx), ic32(7), ic32(offValRead), lget(1), call(fnLogPrefixName),
|
||||
)
|
||||
}
|
||||
|
||||
// get_pending(key) — read pending proposal
|
||||
// Locals: keyLen(0), valLen(1), keyBufLen(2)
|
||||
func getPendingBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(3, tI32)),
|
||||
ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0),
|
||||
lget(0), i32Eqz(), if_(), return_(), end_(),
|
||||
|
||||
ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(2),
|
||||
ic32(offScratch), lget(2), ic32(offValRead), ic32(256), call(fnGetState), lset(1),
|
||||
lget(1), i32Eqz(), if_(),
|
||||
ic32(offNoPendingPfx), ic32(12), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
return_(),
|
||||
end_(),
|
||||
ic32(offPendingPfx), ic32(9), ic32(offValRead), lget(1), call(fnLogPrefixName),
|
||||
)
|
||||
}
|
||||
|
||||
// set_admin(new_admin) — transfer admin role
|
||||
// Locals: newAdminLen(0), callerLen(1), adminLen(2)
|
||||
func setAdminBody() []byte {
|
||||
return funcBody(
|
||||
withLocals(localDecl(3, tI32)),
|
||||
ic32(0), ic32(offArg0), ic32(128), call(fnGetArgStr), lset(0),
|
||||
lget(0), i32Eqz(), if_(), return_(), end_(),
|
||||
|
||||
ic32(offCaller), ic32(128), call(fnGetCaller), lset(1),
|
||||
isCallerAdminCode(1, 2),
|
||||
i32Eqz(), if_(),
|
||||
ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
return_(),
|
||||
end_(),
|
||||
|
||||
ic32(offKeyAdmin), ic32(5), ic32(offArg0), lget(0), call(fnSetState),
|
||||
ic32(offAdminPfx), ic32(7), ic32(offArg0), lget(0), call(fnLogPrefixName),
|
||||
)
|
||||
}
|
||||
|
||||
// ── main ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
func main() {
|
||||
// Types:
|
||||
// 0: (i32,i32,i32)→(i32) get_arg_str, bytes_equal
|
||||
// 1: (i32,i32)→(i32) get_caller
|
||||
// 2: (i32,i32,i32,i32)→(i32) get_state, build_key
|
||||
// 3: (i32,i32,i32,i32)→() set_state, log_prefix_name
|
||||
// 4: (i32,i32)→() log
|
||||
// 5: ()→() exported methods
|
||||
// 6: (i32,i32,i32)→() memcpy
|
||||
typeSection := section(0x01, vec(
|
||||
functype([]byte{tI32, tI32, tI32}, []byte{tI32}), // 0
|
||||
functype([]byte{tI32, tI32}, []byte{tI32}), // 1
|
||||
functype([]byte{tI32, tI32, tI32, tI32}, []byte{tI32}), // 2
|
||||
functype([]byte{tI32, tI32, tI32, tI32}, []byte{}), // 3
|
||||
functype([]byte{tI32, tI32}, []byte{}), // 4
|
||||
functype([]byte{}, []byte{}), // 5
|
||||
functype([]byte{tI32, tI32, tI32}, []byte{}), // 6
|
||||
))
|
||||
|
||||
importSection := section(0x02, vec(
|
||||
importFunc("env", "get_arg_str", 0), // 0 type 0
|
||||
importFunc("env", "get_caller", 1), // 1 type 1
|
||||
importFunc("env", "get_state", 2), // 2 type 2
|
||||
importFunc("env", "set_state", 3), // 3 type 3
|
||||
importFunc("env", "log", 4), // 4 type 4
|
||||
))
|
||||
|
||||
// 11 local functions
|
||||
functionSection := section(0x03, vec(
|
||||
u(0), // bytes_equal type 0
|
||||
u(6), // memcpy type 6
|
||||
u(3), // log_prefix_name type 3
|
||||
u(2), // build_key type 2
|
||||
u(5), // init type 5
|
||||
u(5), // propose type 5
|
||||
u(5), // approve type 5
|
||||
u(5), // reject type 5
|
||||
u(5), // get type 5
|
||||
u(5), // get_pending type 5
|
||||
u(5), // set_admin type 5
|
||||
))
|
||||
|
||||
memorySection := section(0x05, vec(cat([]byte{0x00}, u(2)))) // 2 pages = 128KB
|
||||
|
||||
exportSection := section(0x07, vec(
|
||||
exportEntry("memory", 0x02, 0),
|
||||
exportEntry("init", 0x00, fnInit),
|
||||
exportEntry("propose", 0x00, fnPropose),
|
||||
exportEntry("approve", 0x00, fnApprove),
|
||||
exportEntry("reject", 0x00, fnReject),
|
||||
exportEntry("get", 0x00, fnGet),
|
||||
exportEntry("get_pending", 0x00, fnGetPending),
|
||||
exportEntry("set_admin", 0x00, fnSetAdmin),
|
||||
))
|
||||
|
||||
dataSection := section(0x0B, cat(
|
||||
u(14),
|
||||
dataSegment(offKeyAdmin, []byte("admin")),
|
||||
dataSegment(offPfxParam, []byte("param:")),
|
||||
dataSegment(offPfxProp, []byte("prop:")),
|
||||
dataSegment(offInitedPfx, []byte("initialized: ")),
|
||||
dataSegment(offProposedPfx, []byte("proposed: ")),
|
||||
dataSegment(offApprovedPfx, []byte("approved: ")),
|
||||
dataSegment(offRejectedPfx, []byte("rejected: ")),
|
||||
dataSegment(offValuePfx, []byte("value: ")),
|
||||
dataSegment(offNotSetPfx, []byte("not set: ")),
|
||||
dataSegment(offPendingPfx, []byte("pending: ")),
|
||||
dataSegment(offNoPendingPfx, []byte("no pending: ")),
|
||||
dataSegment(offAdminPfx, []byte("admin: ")),
|
||||
dataSegment(offUnauthPfx, []byte("unauthorized: ")),
|
||||
dataSegment(offAlreadyPfx, []byte("already init")),
|
||||
))
|
||||
|
||||
codeSection := section(0x0A, cat(
|
||||
u(11),
|
||||
bytesEqualBody(),
|
||||
memcpyBody(),
|
||||
logPrefixNameBody(),
|
||||
buildKeyBody(),
|
||||
initBody(),
|
||||
proposeBody(),
|
||||
approveBody(),
|
||||
rejectBody(),
|
||||
getBody(),
|
||||
getPendingBody(),
|
||||
setAdminBody(),
|
||||
))
|
||||
|
||||
module := cat(
|
||||
[]byte{0x00, 0x61, 0x73, 0x6d},
|
||||
[]byte{0x01, 0x00, 0x00, 0x00},
|
||||
typeSection,
|
||||
importSection,
|
||||
functionSection,
|
||||
memorySection,
|
||||
exportSection,
|
||||
dataSection,
|
||||
codeSection,
|
||||
)
|
||||
|
||||
out := "contracts/governance/governance.wasm"
|
||||
if err := os.WriteFile(out, module, 0644); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "write:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Written %s (%d bytes)\n", out, len(module))
|
||||
}
|
||||
Reference in New Issue
Block a user