mirror of
https://github.com/mineracks/seedhammer-v1-companion.git
synced 2026-06-26 22:01:05 +10:00
Twelve packages lifted from seedhammer/seedhammer @ v1.3.0
(commit 2f071c1d8f23eb7fd39b15fc0acb8874113f801e):
address/ — bitcoin address parsing
backup/ — v1 plate dimensions + UR-coded multi-plate backup
bc/ — Blockchain Commons: ur, fountain, bytewords, urtypes,
xoshiro256 (5 subpkgs)
bip32/ — HD-key derivation
bip39/ — mnemonic seed phrases + 2048-word wordlist
engrave/ — text/QR → MoveTo/LineTo command stream conversion
seedqr/ — SeedQR / CompactSeedQR encoders
image/ — paletted, rgb565, alpha4, ninepatch image formats
nonstandard/ — bitcoin descriptor + script parsing
font/ — bitmap + vector font runtime
font/{comfortaa,poppins,constant,bitmap,vector}/ — actual fonts
driver/mjolnir/ — MarkingWay USB-serial engraver driver
Plus an earlier-aside backup_test.go restored (its deps are now lifted).
Import paths globally rewritten seedhammer.com → mineracks namespace
via single sed pass; verified no orphan refs remain. go.mod adopts
upstream's full dep set plus the replace-directive for the patched
kortschak/qr fork.
go build ./... clean (all 27 packages)
go test ./... clean (12 packages with tests, all passing)
NOT lifted in this commit:
- driver/{wshat,drm,libcamera} (hardware-specific GPIO/LCD/camera —
will be platform-v1/-shaped abstractions instead)
- gui/ (depends on the above; lifts in Phase 2)
- cmd/{controller,...} (Pi binary entrypoints — not needed for the
companion repo)
- zbar/ (QR scanner — needs libcamera)
Next:
- Write the SH1E reference encoder/decoder in engrave/wire/sh1e/
- Lift Gangleri42's cmd/webnfc/ shell + retune to v1 plates
- First buildable composer WASM with a working preview
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
188 lines
6.5 KiB
Go
188 lines
6.5 KiB
Go
package bip39
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"testing"
|
|
)
|
|
|
|
func TestVectors(t *testing.T) {
|
|
for _, v := range testVectors {
|
|
m, err := ParseMnemonic(v.mnemonic)
|
|
if err != nil {
|
|
t.Fatalf("mnemonic %q failed to parse: %v", v.mnemonic, err)
|
|
}
|
|
e, err := hex.DecodeString(v.entropy)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
ent, check := splitMnemonic(m)
|
|
if !bytes.Equal(e, ent) {
|
|
t.Errorf("entropy mismatch")
|
|
}
|
|
if want := Checksum(ent); want != check {
|
|
t.Errorf("checksum mismatch, got %d, want %d", check, want)
|
|
}
|
|
checkWord := m[len(m)-1]
|
|
if want := ChecksumWord(ent); want != checkWord {
|
|
t.Errorf("checksum word mismatch, got %d, want %d", checkWord, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInvalidSeeds(t *testing.T) {
|
|
tests := []string{
|
|
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon",
|
|
}
|
|
for _, test := range tests {
|
|
_, err := ParseMnemonic(test)
|
|
if err == nil {
|
|
t.Errorf("successfully parsed invalid seed %q", test)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestChecksumWord(t *testing.T) {
|
|
mnemonic := make(Mnemonic, 12)
|
|
for i := 0; i < 1e4; i++ {
|
|
for j := range mnemonic {
|
|
mnemonic[j] = RandomWord()
|
|
}
|
|
want, _ := splitMnemonic(mnemonic)
|
|
got := mnemonic.FixChecksum().Entropy()
|
|
if !bytes.Equal(want, got) {
|
|
t.Errorf("checksum word changed the entropy")
|
|
}
|
|
}
|
|
}
|
|
|
|
var testVectors = []struct {
|
|
entropy string
|
|
mnemonic string
|
|
}{
|
|
{
|
|
entropy: "00000000000000000000000000000000",
|
|
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
|
},
|
|
{
|
|
entropy: "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
|
mnemonic: "legal winner thank year wave sausage worth useful legal winner thank yellow",
|
|
},
|
|
{
|
|
entropy: "80808080808080808080808080808080",
|
|
mnemonic: "letter advice cage absurd amount doctor acoustic avoid letter advice cage above",
|
|
},
|
|
{
|
|
entropy: "ffffffffffffffffffffffffffffffff",
|
|
mnemonic: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
|
|
},
|
|
{
|
|
entropy: "000000000000000000000000000000000000000000000000",
|
|
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
|
},
|
|
{
|
|
entropy: "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
|
mnemonic: "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will",
|
|
},
|
|
{
|
|
entropy: "808080808080808080808080808080808080808080808080",
|
|
mnemonic: "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always",
|
|
},
|
|
{
|
|
entropy: "ffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
mnemonic: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when",
|
|
},
|
|
{
|
|
entropy: "0000000000000000000000000000000000000000000000000000000000000000",
|
|
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
|
},
|
|
{
|
|
entropy: "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
|
mnemonic: "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title",
|
|
},
|
|
{
|
|
entropy: "8080808080808080808080808080808080808080808080808080808080808080",
|
|
mnemonic: "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless",
|
|
},
|
|
{
|
|
entropy: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
mnemonic: "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote",
|
|
},
|
|
{
|
|
entropy: "9e885d952ad362caeb4efe34a8e91bd2",
|
|
mnemonic: "ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic",
|
|
},
|
|
{
|
|
entropy: "6610b25967cdcca9d59875f5cb50b0ea75433311869e930b",
|
|
mnemonic: "gravity machine north sort system female filter attitude volume fold club stay feature office ecology stable narrow fog",
|
|
},
|
|
{
|
|
entropy: "68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c",
|
|
mnemonic: "hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay length",
|
|
},
|
|
{
|
|
entropy: "c0ba5a8e914111210f2bd131f3d5e08d",
|
|
mnemonic: "scheme spot photo card baby mountain device kick cradle pact join borrow",
|
|
},
|
|
{
|
|
entropy: "6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3",
|
|
mnemonic: "horn tenant knee talent sponsor spell gate clip pulse soap slush warm silver nephew swap uncle crack brave",
|
|
},
|
|
{
|
|
entropy: "9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863",
|
|
mnemonic: "panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside",
|
|
},
|
|
{
|
|
entropy: "23db8160a31d3e0dca3688ed941adbf3",
|
|
mnemonic: "cat swing flag economy stadium alone churn speed unique patch report train",
|
|
},
|
|
{
|
|
entropy: "8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0",
|
|
mnemonic: "light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud access",
|
|
},
|
|
{
|
|
entropy: "066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad",
|
|
mnemonic: "all hour make first leader extend hole alien behind guard gospel lava path output census museum junior mass reopen famous sing advance salt reform",
|
|
},
|
|
{
|
|
entropy: "f30f8c1da665478f49b001d94c5fc452",
|
|
mnemonic: "vessel ladder alter error federal sibling chat ability sun glass valve picture",
|
|
},
|
|
{
|
|
entropy: "c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05",
|
|
mnemonic: "scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk hair mango congress clump",
|
|
},
|
|
{
|
|
entropy: "f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f",
|
|
mnemonic: "void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold",
|
|
},
|
|
}
|
|
|
|
func TestDiceToWord(t *testing.T) {
|
|
counts := make([]int, len(index))
|
|
dice := Roll{1, 1, 1, 1, 1}
|
|
loop:
|
|
for {
|
|
word, valid := DiceToWord(dice)
|
|
// Increment roll.
|
|
for i := len(dice) - 1; ; i-- {
|
|
if i < 0 {
|
|
break loop
|
|
}
|
|
dice[i]++
|
|
if dice[i] <= 6 {
|
|
break
|
|
}
|
|
dice[i] = 1
|
|
}
|
|
if valid {
|
|
counts[word]++
|
|
}
|
|
}
|
|
for word, count := range counts {
|
|
if count != 3 {
|
|
t.Errorf("word %v chosen %d times, expected 3", word, count)
|
|
}
|
|
}
|
|
}
|