wire/wire_test.go
188 lines
1package wire23import (4"bytes"5"crypto/sha256"6"encoding/binary"7"testing"89"peoplecoin/params"10)1112func addr(b byte) Address {13var a Address14for i := range a {15a[i] = b16}17return a18}1920func TestCoinEntryRoundTrip(t *testing.T) {21e := &CoinEntry{Owners: []Address{addr(1), addr(2), addr(3)}, Threshold: 2, Amount: 123456789, Slot: 40320}22b := e.Bytes()23if len(b) != 1+96+1+8+4 {24t.Fatalf("length %d", len(b))25}26if b[0] != 3 || b[97] != 2 || binary.BigEndian.Uint64(b[98:]) != 123456789 || binary.BigEndian.Uint32(b[106:]) != 40320 {27t.Fatal("layout")28}29d, err := DecodeCoinEntry(b)30if err != nil || d.Threshold != 2 || d.Amount != 123456789 || d.Slot != 40320 || len(d.Owners) != 3 || d.Owners[2] != addr(3) {31t.Fatalf("decode: %v %+v", err, d)32}33if !bytes.Equal(d.Bytes(), b) {34t.Fatal("re-encode")35}36// Strictness.37if _, err := DecodeCoinEntry(append(b, 0)); err == nil {38t.Fatal("trailing byte accepted")39}40if _, err := DecodeCoinEntry(b[:len(b)-1]); err == nil {41t.Fatal("truncated accepted")42}43if _, err := DecodeCoinEntry([]byte{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); err == nil {44t.Fatal("zero owners accepted")45}46nine := &CoinEntry{Owners: make([]Address, 9), Threshold: 1, Amount: 1}47if _, err := DecodeCoinEntry(nine.Bytes()); err == nil {48t.Fatal("nine owners accepted")49}50zeroT := &CoinEntry{Owners: []Address{addr(1)}, Threshold: 0, Amount: 1}51if _, err := DecodeCoinEntry(zeroT.Bytes()); err == nil {52t.Fatal("threshold 0 accepted")53}54bigT := &CoinEntry{Owners: []Address{addr(1)}, Threshold: 2, Amount: 1}55if _, err := DecodeCoinEntry(bigT.Bytes()); err == nil {56t.Fatal("threshold > owners accepted")57}58}5960func TestTokenEntryRoundTrip(t *testing.T) {61e := &TokenEntry{TokenID: params.TokenInvite, Owner: addr(9), MixCount: 31}62b := e.Bytes()63if len(b) != 37 || b[0] != 2 || binary.BigEndian.Uint32(b[33:]) != 31 {64t.Fatal("layout")65}66d, err := DecodeTokenEntry(b)67if err != nil || *d != *e {68t.Fatalf("decode: %v", err)69}70if _, err := DecodeTokenEntry(b[:36]); err == nil {71t.Fatal("truncated accepted")72}73}7475func TestRegEntryRoundTrip(t *testing.T) {76for _, e := range []RegEntry{{}, {Verify: true}, {Verify: true, Verified: true}, {Verified: true}} {77b := e.Bytes()78d, err := DecodeRegEntry(b)79if err != nil || *d != e {80t.Fatalf("decode %v: %v", e, err)81}82}83if _, err := DecodeRegEntry([]byte{2, 0}); err == nil {84t.Fatal("non-boolean byte accepted")85}86if _, err := DecodeRegEntry([]byte{1}); err == nil {87t.Fatal("short accepted")88}89}9091func TestHashEntries(t *testing.T) {92c := sha256.Sum256([]byte("c"))93r, err := DecodeRngEntry((&RngEntry{Commit: c}).Bytes())94if err != nil || r.Commit != c {95t.Fatal("rng entry")96}97e, err := DecodeElectionEntry((&ElectionEntry{Commit: c}).Bytes())98if err != nil || e.Commit != c {99t.Fatal("election entry")100}101if _, err := DecodeRngEntry(c[:31]); err == nil {102t.Fatal("short rng accepted")103}104}105106func TestEncoders(t *testing.T) {107ids := []Address{addr(1), addr(2)}108b, err := EncodeIDs(ids)109if err != nil || len(b) != 65 || b[0] != 2 || !bytes.Equal(b[33:], ids[1][:]) {110t.Fatal("ids")111}112if _, err := EncodeIDs(make([]Address, 256)); err != ErrTooMany {113t.Fatal("256 ids accepted")114}115tb, err := EncodeTransferOutputs([]TransferOutput{{Amount: 5, Owners: []Address{addr(7)}, Threshold: 1}})116if err != nil || len(tb) != 1+8+1+32+1 || tb[0] != 1 || binary.BigEndian.Uint64(tb[1:]) != 5 || tb[9] != 1 || tb[42] != 1 {117t.Fatal("transfer outputs")118}119mb, err := EncodeMixOutputs([]MixOutput{{MixCount: 3, Owner: addr(4)}})120if err != nil || len(mb) != 1+4+32 || binary.BigEndian.Uint32(mb[1:]) != 3 {121t.Fatal("mix outputs")122}123}124125func cat(parts ...[]byte) []byte { return bytes.Join(parts, nil) }126127func sl(a Address) []byte { return a[:] }128129func TestSigningMessages(t *testing.T) {130inputs := []Address{addr(1)}131outputs := []TransferOutput{{Amount: 10, Owners: []Address{addr(2)}, Threshold: 1}}132in, _ := EncodeIDs(inputs)133out, _ := EncodeTransferOutputs(outputs)134hi, ho := sha256.Sum256(in), sha256.Sum256(out)135want := sha256.Sum256(cat([]byte{0x00}, hi[:], ho[:]))136if got, _ := TransferMessage(inputs, outputs); got != want {137t.Fatal("transfer message")138}139140mo := []MixOutput{{MixCount: 1, Owner: addr(3)}}141mob, _ := EncodeMixOutputs(mo)142hmo := sha256.Sum256(mob)143want = sha256.Sum256(cat([]byte{0x01, 0x02}, hi[:], hmo[:]))144if got, _ := MixMessage(2, inputs, mo); got != want {145t.Fatal("mix message")146}147148c := sha256.Sum256([]byte("commit"))149if VoteMessage(addr(1), c) != sha256.Sum256(cat([]byte{0x02}, sl(addr(1)), c[:])) {150t.Fatal("vote message")151}152want = sha256.Sum256(cat([]byte{0x03}, hi[:]))153if got, _ := RegisterMessage(inputs); got != want {154t.Fatal("register message")155}156per := []byte{0, 0, 0, 7}157if VerifyMessage(7, addr(5)) != sha256.Sum256(cat([]byte{0x04}, per, sl(addr(5)))) {158t.Fatal("verify message")159}160if VerifiedMessage(7, addr(5)) != sha256.Sum256(cat([]byte{0x05}, per, sl(addr(5)))) {161t.Fatal("verified message")162}163if CommitMessage(7, addr(5), c) != sha256.Sum256(cat([]byte{0x06}, per, sl(addr(5)), c[:])) {164t.Fatal("commit message")165}166if RevealMessage(7, addr(5), c) != sha256.Sum256(cat([]byte{0x07}, per, sl(addr(5)), c[:])) {167t.Fatal("reveal message")168}169if PruneMessage(addr(6)) != sha256.Sum256(cat([]byte{0xFF}, sl(addr(6)))) {170t.Fatal("prune message")171}172173// Cross-operation and cross-period separation.174if VerifyMessage(7, addr(5)) == VerifiedMessage(7, addr(5)) || VerifyMessage(7, addr(5)) == VerifyMessage(8, addr(5)) {175t.Fatal("messages must differ by opcode and period")176}177}178179func TestIdentifiers(t *testing.T) {180tx := sha256.Sum256([]byte("tx"))181if UTXOID(tx, 2) != sha256.Sum256(cat(tx[:], []byte{2})) {182t.Fatal("utxo id")183}184if FeeUTXOID(0x0102, 1) != sha256.Sum256([]byte{0, 0, 0, 0, 0, 0, 1, 2, 1}) {185t.Fatal("fee utxo id")186}187}