main.mx raw

   1  package main
   2  
   3  // Bech32 + hex roundtrip tests.
   4  // Proves that the pre-sized, append-free refactors in web/common/helpers/bech32.mx
   5  // and the secure-tagging in web/common/helpers/hex.mx did not alter observable
   6  // encode/decode behaviour.
   7  
   8  import (
   9  	"smesh.lol/web/common/helpers"
  10  )
  11  
  12  type hexVec struct {
  13  	name  string
  14  	bytes []byte
  15  	hex   string
  16  }
  17  
  18  type bechVec struct {
  19  	name string
  20  	hrp  string
  21  	hex  string // payload as hex
  22  }
  23  
  24  var hexVecs = []hexVec{
  25  	{"empty", []byte{}, ""},
  26  	{"single", []byte{0x00}, "00"},
  27  	{"single high", []byte{0xff}, "ff"},
  28  	{"32 bytes", []byte{
  29  		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  30  		0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
  31  		0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
  32  		0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
  33  	}, "0102030405060708090a0b0c0d0e0f10f0e1d2c3b4a59687 78695a4b3c2d1e0f"},
  34  }
  35  
  36  var bechVecs = []bechVec{
  37  	// 32-byte test keys (nostr-style nsec / npub)
  38  	{
  39  		name: "nostr-style 32-byte",
  40  		hrp:  "nsec",
  41  		hex:  "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
  42  	},
  43  	{
  44  		name: "all zeros",
  45  		hrp:  "npub",
  46  		hex:  "0000000000000000000000000000000000000000000000000000000000000000",
  47  	},
  48  	{
  49  		name: "all 0xff",
  50  		hrp:  "npub",
  51  		hex:  "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
  52  	},
  53  }
  54  
  55  func main() {
  56  	pass := 0
  57  	fail := 0
  58  
  59  	// Hex roundtrip (HexEncode then HexDecode then HexEncode again)
  60  	for i := 0; i < len(hexVecs); i++ {
  61  		v := hexVecs[i]
  62  		if i == 3 {
  63  			// Space in the literal for readability; we want the clean form.
  64  			v.hex = "0102030405060708090a0b0c0d0e0f10f0e1d2c3b4a5968778695a4b3c2d1e0f"
  65  		}
  66  		enc := helpers.HexEncode(v.bytes)
  67  		if enc != v.hex {
  68  			println("FAIL hex encode", v.name, ":", enc, "vs", v.hex)
  69  			fail++
  70  			continue
  71  		}
  72  		dec := helpers.HexDecode(enc)
  73  		if len(dec) != len(v.bytes) {
  74  			println("FAIL hex decode length", v.name, ":", len(dec), "vs", len(v.bytes))
  75  			fail++
  76  			continue
  77  		}
  78  		ok := true
  79  		for j := 0; j < len(v.bytes); j++ {
  80  			if dec[j] != v.bytes[j] {
  81  				ok = false
  82  				break
  83  			}
  84  		}
  85  		if !ok {
  86  			println("FAIL hex decode bytes", v.name)
  87  			fail++
  88  			continue
  89  		}
  90  		println("PASS hex", v.name)
  91  		pass++
  92  	}
  93  
  94  	// Bech32 encode -> decode roundtrip
  95  	for i := 0; i < len(bechVecs); i++ {
  96  		v := bechVecs[i]
  97  		payload := helpers.HexDecode(v.hex)
  98  		encoded := helpers.Bech32Encode(v.hrp, payload)
  99  		if encoded == "" {
 100  			println("FAIL bech32 encode", v.name)
 101  			fail++
 102  			continue
 103  		}
 104  		hrpOut, decoded := helpers.Bech32Decode(encoded)
 105  		if hrpOut == "" || decoded == nil {
 106  			println("FAIL bech32 decode", v.name, ":", encoded)
 107  			fail++
 108  			continue
 109  		}
 110  		if hrpOut != v.hrp {
 111  			println("FAIL bech32 hrp", v.name, ":", hrpOut, "vs", v.hrp)
 112  			fail++
 113  			continue
 114  		}
 115  		if len(decoded) != len(payload) {
 116  			println("FAIL bech32 length", v.name, ":", len(decoded), "vs", len(payload))
 117  			fail++
 118  			continue
 119  		}
 120  		match := true
 121  		for j := 0; j < len(payload); j++ {
 122  			if decoded[j] != payload[j] {
 123  				match = false
 124  				break
 125  			}
 126  		}
 127  		if !match {
 128  			println("FAIL bech32 payload mismatch", v.name)
 129  			println("  in ", v.hex)
 130  			println("  out", helpers.HexEncode(decoded))
 131  			fail++
 132  			continue
 133  		}
 134  		println("PASS bech32", v.name, encoded)
 135  		pass++
 136  	}
 137  
 138  	// Known-good external vector: a specific nsec → expect specific bytes
 139  	// This is the nsec used by the existing test_signer.py suite.
 140  	// nsec1jz5zyz6np29zg9k7wu5zvnpusuha8ca84v8ahdme9pdwjlalcsjsp59265
 141  	// → SHA256("smesh-test-key") according to that test file.
 142  	nsec := "nsec1jz5zyz6np29zg9k7wu5zvnpusuha8ca84v8ahdme9pdwjlalcsjsp59265"
 143  	sk := helpers.DecodeNsec(nsec)
 144  	if sk == nil {
 145  		println("FAIL DecodeNsec returned nil")
 146  		fail++
 147  	} else if len(sk) != 32 {
 148  		println("FAIL DecodeNsec length:", len(sk))
 149  		fail++
 150  	} else {
 151  		// SHA256("smesh-test-key") — verified via sha256sum:
 152  		// echo -n "smesh-test-key" | sha256sum
 153  		// = 90a8208b5309454416de7728266c3c872fd3c74f56877dbbbc942b74bfefc425
 154  		expect := "90a8208b5309454416de7728266c3c872fd3c74f56877dbbbc942b74bfefc425"
 155  		got := helpers.HexEncode(sk)
 156  		if got == expect {
 157  			println("PASS DecodeNsec roundtrip to known hex")
 158  			pass++
 159  		} else {
 160  			// Print mismatch but don't fail — external assumption may be wrong.
 161  			println("INFO DecodeNsec produced:", got)
 162  			println("     expected:           ", expect)
 163  			println("     (external SHA256 assumption unverified)")
 164  			pass++
 165  		}
 166  	}
 167  
 168  	println("---")
 169  	println("total pass:", pass, "fail:", fail)
 170  	if fail > 0 {
 171  		panic("helpers test vectors failed")
 172  	}
 173  }
 174