decred.org/dcrdex@v1.0.5/dex/msgjson/msg_test.go (about)

     1  package msgjson
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"errors"
     8  	"math/rand"
     9  	"strings"
    10  	"testing"
    11  
    12  	"decred.org/dcrdex/server/account"
    13  )
    14  
    15  func TestMessageUnmarshal(t *testing.T) {
    16  	// Test null payload handling. NO error.
    17  	msg := Message{
    18  		Payload: []byte(`null`),
    19  	}
    20  
    21  	type Payload struct{}
    22  
    23  	payload := new(Payload)
    24  	err := msg.Unmarshal(payload) // *Payload
    25  	if err != nil {
    26  		t.Errorf("expected no error, got %v", err)
    27  	}
    28  	if payload == nil {
    29  		t.Errorf("expected payload to not be nil")
    30  	}
    31  
    32  	payload = new(Payload)
    33  	err = msg.Unmarshal(&payload) // **Payload
    34  	if err != nil {
    35  		t.Errorf("expected no error, got %v", err)
    36  	}
    37  	if payload != nil {
    38  		t.Errorf("expected payload to be nil")
    39  	}
    40  }
    41  
    42  func TestMessageResponse(t *testing.T) {
    43  	// Test null payload, expecting errNullRespPayload.
    44  	msg := Message{
    45  		Type:    Response,
    46  		Payload: []byte(`null`),
    47  	}
    48  
    49  	respPayload, err := msg.Response()
    50  	if !errors.Is(err, errNullRespPayload) {
    51  		t.Fatalf("expected a errNullRespPayload, got %v", err)
    52  	}
    53  	if respPayload != nil {
    54  		t.Errorf("response payload should have been nil")
    55  	}
    56  
    57  	// Test bad/empty json, expecting "unexpected end of JSON input".
    58  	msg.Payload = []byte(``)
    59  	respPayload, err = msg.Response()
    60  	const wantErrStr = "unexpected end of JSON input"
    61  	if err == nil || !strings.Contains(err.Error(), wantErrStr) {
    62  		t.Fatalf("expected error with %q, got %q", wantErrStr, err)
    63  	}
    64  	if respPayload != nil {
    65  		t.Errorf("response payload should have been nil")
    66  	}
    67  }
    68  
    69  func TestMatch(t *testing.T) {
    70  	// serialization: orderid (32) + matchid (8) + qty (8) + rate (8)
    71  	// + address (varies)
    72  	oid, _ := hex.DecodeString("2219c5f3a03407c87211748c884404e2f466cba19616faca1cda0010ca5db0d3")
    73  	mid, _ := hex.DecodeString("4969784b00a59dd0340952c9b8f52840fbb32e9b51d4f6e18cbec7f50c8a3ed7")
    74  	match := &Match{
    75  		OrderID:      oid,
    76  		MatchID:      mid,
    77  		Quantity:     5e8,
    78  		Rate:         uint64(2e8),
    79  		ServerTime:   1585043380123,
    80  		Address:      "DcqXswjTPnUcd4FRCkX4vRJxmVtfgGVa5ui",
    81  		FeeRateBase:  65536 + 255,
    82  		FeeRateQuote: (1 << 32) + 256 + 1,
    83  	}
    84  	exp := []byte{
    85  		// Order ID 32 bytes
    86  		0x22, 0x19, 0xc5, 0xf3, 0xa0, 0x34, 0x07, 0xc8, 0x72, 0x11, 0x74, 0x8c, 0x88,
    87  		0x44, 0x04, 0xe2, 0xf4, 0x66, 0xcb, 0xa1, 0x96, 0x16, 0xfa, 0xca, 0x1c, 0xda,
    88  		0x00, 0x10, 0xca, 0x5d, 0xb0, 0xd3,
    89  		// Match ID 32 bytes
    90  		0x49, 0x69, 0x78, 0x4b, 0x00, 0xa5, 0x9d, 0xd0, 0x34, 0x09, 0x52, 0xc9, 0xb8,
    91  		0xf5, 0x28, 0x40, 0xfb, 0xb3, 0x2e, 0x9b, 0x51, 0xd4, 0xf6, 0xe1, 0x8c, 0xbe,
    92  		0xc7, 0xf5, 0x0c, 0x8a, 0x3e, 0xd7,
    93  		// quantity 8 bytes
    94  		0x00, 0x00, 0x00, 0x00, 0x1d, 0xcd, 0x65, 0x00,
    95  		// rate 8 bytes
    96  		0x00, 0x00, 0x00, 0x00, 0x0b, 0xeb, 0xc2, 0x00,
    97  		// timestamp 8 bytes
    98  		0x00, 0x00, 0x01, 0x71, 0x0b, 0xf2, 0x97, 0x9b,
    99  		// address - utf-8 encoding
   100  		0x44, 0x63, 0x71, 0x58, 0x73, 0x77, 0x6a, 0x54, 0x50, 0x6e, 0x55, 0x63, 0x64,
   101  		0x34, 0x46, 0x52, 0x43, 0x6b, 0x58, 0x34, 0x76, 0x52, 0x4a, 0x78, 0x6d, 0x56,
   102  		0x74, 0x66, 0x67, 0x47, 0x56, 0x61, 0x35, 0x75, 0x69,
   103  		// base fee rate 8 bytes
   104  		0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0xff,
   105  		// quote fee rate 8 bytes
   106  		0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1,
   107  	}
   108  
   109  	b := match.Serialize()
   110  	if !bytes.Equal(b, exp) {
   111  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   112  	}
   113  
   114  	matchB, err := json.Marshal(match)
   115  	if err != nil {
   116  		t.Fatalf("marshal error: %v", err)
   117  	}
   118  
   119  	var matchBack Match
   120  	err = json.Unmarshal(matchB, &matchBack)
   121  	if err != nil {
   122  		t.Fatalf("unmarshal error: %v", err)
   123  	}
   124  
   125  	if !bytes.Equal(matchBack.MatchID, match.MatchID) {
   126  		t.Fatal(matchBack.MatchID, match.MatchID)
   127  	}
   128  	if !bytes.Equal(matchBack.OrderID, match.OrderID) {
   129  		t.Fatal(matchBack.OrderID, match.OrderID)
   130  	}
   131  	if matchBack.Quantity != match.Quantity {
   132  		t.Fatal(matchBack.Quantity, match.Quantity)
   133  	}
   134  	if matchBack.Rate != match.Rate {
   135  		t.Fatal(matchBack.Rate, match.Rate)
   136  	}
   137  	if matchBack.ServerTime != match.ServerTime {
   138  		t.Fatal(matchBack.ServerTime, match.ServerTime)
   139  	}
   140  	if matchBack.Address != match.Address {
   141  		t.Fatal(matchBack.Address, match.Address)
   142  	}
   143  }
   144  
   145  func TestInit(t *testing.T) {
   146  	// serialization: orderid (32) + matchid (32) + txid (probably 64) + vout (4)
   147  	// + contract (97 ish)
   148  	oid, _ := hex.DecodeString("ceb09afa675cee31c0f858b94c81bd1a4c2af8c5947d13e544eef772381f2c8d")
   149  	mid, _ := hex.DecodeString("7c6b44735e303585d644c713fe0e95897e7e8ba2b9bba98d6d61b70006d3d58c")
   150  	coinid, _ := hex.DecodeString("c3161033de096fd74d9051ff0bd99e359de35080a3511081ed035f541b850d4300000005")
   151  	contract, _ := hex.DecodeString("caf8d277f80f71e4")
   152  	init := &Init{
   153  		OrderID:  oid,
   154  		MatchID:  mid,
   155  		CoinID:   coinid,
   156  		Contract: contract,
   157  	}
   158  
   159  	exp := []byte{
   160  		// Order ID 32 bytes
   161  		0xce, 0xb0, 0x9a, 0xfa, 0x67, 0x5c, 0xee, 0x31, 0xc0, 0xf8, 0x58, 0xb9,
   162  		0x4c, 0x81, 0xbd, 0x1a, 0x4c, 0x2a, 0xf8, 0xc5, 0x94, 0x7d, 0x13, 0xe5,
   163  		0x44, 0xee, 0xf7, 0x72, 0x38, 0x1f, 0x2c, 0x8d,
   164  		// Match ID 32 bytes
   165  		0x7c, 0x6b, 0x44, 0x73, 0x5e, 0x30, 0x35, 0x85, 0xd6, 0x44, 0xc7, 0x13,
   166  		0xfe, 0x0e, 0x95, 0x89, 0x7e, 0x7e, 0x8b, 0xa2, 0xb9, 0xbb, 0xa9, 0x8d,
   167  		0x6d, 0x61, 0xb7, 0x00, 0x06, 0xd3, 0xd5, 0x8c,
   168  		// Coin ID 36 bytes
   169  		0xc3, 0x16, 0x10, 0x33, 0xde, 0x09, 0x6f, 0xd7, 0x4d, 0x90, 0x51, 0xff,
   170  		0x0b, 0xd9, 0x9e, 0x35, 0x9d, 0xe3, 0x50, 0x80, 0xa3, 0x51, 0x10, 0x81,
   171  		0xed, 0x03, 0x5f, 0x54, 0x1b, 0x85, 0x0d, 0x43, 0x00, 0x00, 0x00, 0x05,
   172  		// Contract 8 bytes (shortened for testing)
   173  		0xca, 0xf8, 0xd2, 0x77, 0xf8, 0x0f, 0x71, 0xe4,
   174  	}
   175  	b := init.Serialize()
   176  	if !bytes.Equal(b, exp) {
   177  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   178  	}
   179  
   180  	initB, err := json.Marshal(init)
   181  	if err != nil {
   182  		t.Fatalf("marshal error: %v", err)
   183  	}
   184  
   185  	var initBack Init
   186  	err = json.Unmarshal(initB, &initBack)
   187  	if err != nil {
   188  		t.Fatalf("unmarshal error: %v", err)
   189  	}
   190  
   191  	if !bytes.Equal(initBack.MatchID, init.MatchID) {
   192  		t.Fatal(initBack.MatchID, init.MatchID)
   193  	}
   194  	if !bytes.Equal(initBack.OrderID, init.OrderID) {
   195  		t.Fatal(initBack.OrderID, init.OrderID)
   196  	}
   197  	if !bytes.Equal(initBack.CoinID, init.CoinID) {
   198  		t.Fatal(initBack.CoinID, init.CoinID)
   199  	}
   200  	if !bytes.Equal(initBack.Contract, init.Contract) {
   201  		t.Fatal(initBack.Contract, init.Contract)
   202  	}
   203  }
   204  
   205  func TestAudit(t *testing.T) {
   206  	// serialization: orderid (32) + matchid (32) + time (8) + coin ID (36)
   207  	// + contract (97 ish)
   208  	oid, _ := hex.DecodeString("d6c752bb34d833b6e0eb4d114d690d044f8ab3f6de9defa08e9d7d237f670fe4")
   209  	mid, _ := hex.DecodeString("79f84ef6c60e72edd305047c015d7b7ade64525a301fdac136976f05edb6172b")
   210  	coinID, _ := hex.DecodeString("3cdabd9bd62dfbd7d8b020d5de4e643b439886f4b0dc86cb8a56dff8e61c5ec333487a97")
   211  	contract, _ := hex.DecodeString("fc99f576f8e0e5dc")
   212  	audit := &Audit{
   213  		OrderID:  oid,
   214  		MatchID:  mid,
   215  		Time:     1570705920,
   216  		CoinID:   coinID,
   217  		Contract: contract,
   218  	}
   219  
   220  	exp := []byte{
   221  		// Order ID 32 bytes
   222  		0xd6, 0xc7, 0x52, 0xbb, 0x34, 0xd8, 0x33, 0xb6, 0xe0, 0xeb, 0x4d, 0x11,
   223  		0x4d, 0x69, 0x0d, 0x04, 0x4f, 0x8a, 0xb3, 0xf6, 0xde, 0x9d, 0xef, 0xa0,
   224  		0x8e, 0x9d, 0x7d, 0x23, 0x7f, 0x67, 0x0f, 0xe4,
   225  		// Match ID 32 bytes
   226  		0x79, 0xf8, 0x4e, 0xf6, 0xc6, 0x0e, 0x72, 0xed, 0xd3, 0x05, 0x04, 0x7c,
   227  		0x01, 0x5d, 0x7b, 0x7a, 0xde, 0x64, 0x52, 0x5a, 0x30, 0x1f, 0xda, 0xc1,
   228  		0x36, 0x97, 0x6f, 0x05, 0xed, 0xb6, 0x17, 0x2b,
   229  		// Timestamp 8 bytes
   230  		0x00, 0x00, 0x00, 0x00, 0x5d, 0x9f, 0x12, 0x00,
   231  		// Coin ID
   232  		0x3c, 0xda, 0xbd, 0x9b, 0xd6, 0x2d, 0xfb, 0xd7, 0xd8, 0xb0, 0x20, 0xd5,
   233  		0xde, 0x4e, 0x64, 0x3b, 0x43, 0x98, 0x86, 0xf4, 0xb0, 0xdc, 0x86, 0xcb,
   234  		0x8a, 0x56, 0xdf, 0xf8, 0xe6, 0x1c, 0x5e, 0xc3, 0x33, 0x48, 0x7a, 0x97,
   235  		// Contract 8 bytes (shortened for testing)
   236  		0xfc, 0x99, 0xf5, 0x76, 0xf8, 0xe0, 0xe5, 0xdc,
   237  	}
   238  
   239  	b := audit.Serialize()
   240  	if !bytes.Equal(b, exp) {
   241  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   242  	}
   243  
   244  	auditB, err := json.Marshal(audit)
   245  	if err != nil {
   246  		t.Fatalf("marshal error: %v", err)
   247  	}
   248  
   249  	var auditBack Audit
   250  	err = json.Unmarshal(auditB, &auditBack)
   251  	if err != nil {
   252  		t.Fatalf("unmarshal error: %v", err)
   253  	}
   254  
   255  	if !bytes.Equal(auditBack.MatchID, audit.MatchID) {
   256  		t.Fatal(auditBack.MatchID, audit.MatchID)
   257  	}
   258  	if !bytes.Equal(auditBack.OrderID, audit.OrderID) {
   259  		t.Fatal(auditBack.OrderID, audit.OrderID)
   260  	}
   261  	if auditBack.Time != audit.Time {
   262  		t.Fatal(auditBack.Time, audit.Time)
   263  	}
   264  	if !bytes.Equal(auditBack.Contract, audit.Contract) {
   265  		t.Fatal(auditBack.Contract, audit.Contract)
   266  	}
   267  }
   268  
   269  func TestRevokeMatch(t *testing.T) {
   270  	// serialization: order id (32) + match id (32)
   271  	oid, _ := hex.DecodeString("47b903b6e71a1fff3ec1be25b23228bf2e8682b1502dc451f7a9aa32556123f2")
   272  	mid, _ := hex.DecodeString("be218305e71b07a11c59c1b6c3ad3cf6ad4ed7582da8c639b87188aa95795c16")
   273  	revoke := &RevokeMatch{
   274  		OrderID: oid,
   275  		MatchID: mid,
   276  	}
   277  
   278  	exp := []byte{
   279  		// Order ID 32 bytes
   280  		0x47, 0xb9, 0x03, 0xb6, 0xe7, 0x1a, 0x1f, 0xff, 0x3e, 0xc1, 0xbe, 0x25,
   281  		0xb2, 0x32, 0x28, 0xbf, 0x2e, 0x86, 0x82, 0xb1, 0x50, 0x2d, 0xc4, 0x51,
   282  		0xf7, 0xa9, 0xaa, 0x32, 0x55, 0x61, 0x23, 0xf2,
   283  		// Match ID 32 bytes
   284  		0xbe, 0x21, 0x83, 0x05, 0xe7, 0x1b, 0x07, 0xa1, 0x1c, 0x59, 0xc1, 0xb6,
   285  		0xc3, 0xad, 0x3c, 0xf6, 0xad, 0x4e, 0xd7, 0x58, 0x2d, 0xa8, 0xc6, 0x39,
   286  		0xb8, 0x71, 0x88, 0xaa, 0x95, 0x79, 0x5c, 0x16,
   287  	}
   288  
   289  	b := revoke.Serialize()
   290  	if !bytes.Equal(b, exp) {
   291  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   292  	}
   293  
   294  	revB, err := json.Marshal(revoke)
   295  	if err != nil {
   296  		t.Fatalf("marshal error: %v", err)
   297  	}
   298  
   299  	var revokeBack RevokeMatch
   300  	err = json.Unmarshal(revB, &revokeBack)
   301  	if err != nil {
   302  		t.Fatalf("unmarshal error: %v", err)
   303  	}
   304  
   305  	if !bytes.Equal(revokeBack.MatchID, revoke.MatchID) {
   306  		t.Fatal(revokeBack.MatchID, revoke.MatchID)
   307  	}
   308  	if !bytes.Equal(revokeBack.OrderID, revoke.OrderID) {
   309  		t.Fatal(revokeBack.OrderID, revoke.OrderID)
   310  	}
   311  }
   312  
   313  func TestRedeem(t *testing.T) {
   314  	// Redeem serialization is orderid (32) + matchid (32) + coin ID (36) +
   315  	// secret (32) = 132
   316  	oid, _ := hex.DecodeString("ee17139af2d86bd6052829389c0531f71042ed0b0539e617213a9a7151215a1b")
   317  	mid, _ := hex.DecodeString("6ea1227b03d7bf05ce1e23f3edf57368f69ba9ee0cc069f09ab0952a36d964c5")
   318  	coinid, _ := hex.DecodeString("28cb86e678f647cc88da734eed11286dab18b8483feb04580e3cbc90555a004700000005")
   319  	secret, _ := hex.DecodeString("f1df467afb1e0803cefa25e76cf00e07a99416087f6c9d10921bbbb55be5ded9")
   320  	redeem := &Redeem{
   321  		OrderID: oid,
   322  		MatchID: mid,
   323  		CoinID:  coinid,
   324  		Secret:  secret,
   325  	}
   326  
   327  	exp := []byte{
   328  		// Order ID 32 bytes
   329  		0xee, 0x17, 0x13, 0x9a, 0xf2, 0xd8, 0x6b, 0xd6, 0x05, 0x28, 0x29, 0x38,
   330  		0x9c, 0x05, 0x31, 0xf7, 0x10, 0x42, 0xed, 0x0b, 0x05, 0x39, 0xe6, 0x17,
   331  		0x21, 0x3a, 0x9a, 0x71, 0x51, 0x21, 0x5a, 0x1b,
   332  		// Match ID 32 bytes
   333  		0x6e, 0xa1, 0x22, 0x7b, 0x03, 0xd7, 0xbf, 0x05, 0xce, 0x1e, 0x23, 0xf3,
   334  		0xed, 0xf5, 0x73, 0x68, 0xf6, 0x9b, 0xa9, 0xee, 0x0c, 0xc0, 0x69, 0xf0,
   335  		0x9a, 0xb0, 0x95, 0x2a, 0x36, 0xd9, 0x64, 0xc5,
   336  		// Coin ID, 36 Bytes
   337  		0x28, 0xcb, 0x86, 0xe6, 0x78, 0xf6, 0x47, 0xcc, 0x88, 0xda, 0x73, 0x4e,
   338  		0xed, 0x11, 0x28, 0x6d, 0xab, 0x18, 0xb8, 0x48, 0x3f, 0xeb, 0x04, 0x58,
   339  		0x0e, 0x3c, 0xbc, 0x90, 0x55, 0x5a, 0x00, 0x47, 0x00, 0x00, 0x00, 0x05,
   340  		// Secret 32 bytes
   341  		0xf1, 0xdf, 0x46, 0x7a, 0xfb, 0x1e, 0x08, 0x03, 0xce, 0xfa, 0x25, 0xe7,
   342  		0x6c, 0xf0, 0x0e, 0x07, 0xa9, 0x94, 0x16, 0x08, 0x7f, 0x6c, 0x9d, 0x10,
   343  		0x92, 0x1b, 0xbb, 0xb5, 0x5b, 0xe5, 0xde, 0xd9,
   344  	}
   345  
   346  	b := redeem.Serialize()
   347  	if !bytes.Equal(b, exp) {
   348  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   349  	}
   350  
   351  	redeemB, err := json.Marshal(redeem)
   352  	if err != nil {
   353  		t.Fatalf("marshal error: %v", err)
   354  	}
   355  
   356  	var redeemBack Redeem
   357  	err = json.Unmarshal(redeemB, &redeemBack)
   358  	if err != nil {
   359  		t.Fatalf("unmarshal error: %v", err)
   360  	}
   361  
   362  	if !bytes.Equal(redeemBack.MatchID, redeem.MatchID) {
   363  		t.Fatal(redeemBack.MatchID, redeem.MatchID)
   364  	}
   365  	if !bytes.Equal(redeemBack.OrderID, redeem.OrderID) {
   366  		t.Fatal(redeemBack.OrderID, redeem.OrderID)
   367  	}
   368  	if !bytes.Equal(redeemBack.CoinID, redeem.CoinID) {
   369  		t.Fatal(redeemBack.CoinID, redeem.CoinID)
   370  	}
   371  }
   372  
   373  func TestRedemption(t *testing.T) {
   374  	// serialization: orderid (32) + matchid (32) + txid (probably 64) + vout (4)
   375  	// + timestamp (8)
   376  	oid, _ := hex.DecodeString("ee17139af2d86bd6052829389c0531f71042ed0b0539e617213a9a7151215a1b")
   377  	mid, _ := hex.DecodeString("6ea1227b03d7bf05ce1e23f3edf57368f69ba9ee0cc069f09ab0952a36d964c5")
   378  	coinid, _ := hex.DecodeString("28cb86e678f647cc88da734eed11286dab18b8483feb04580e3cbc90555a004700000005")
   379  	redeem := &Redemption{
   380  		Redeem: Redeem{
   381  			OrderID: oid,
   382  			MatchID: mid,
   383  			CoinID:  coinid,
   384  		},
   385  		Time: 1570706834,
   386  	}
   387  
   388  	exp := []byte{
   389  		// Order ID 32 bytes
   390  		0xee, 0x17, 0x13, 0x9a, 0xf2, 0xd8, 0x6b, 0xd6, 0x05, 0x28, 0x29, 0x38,
   391  		0x9c, 0x05, 0x31, 0xf7, 0x10, 0x42, 0xed, 0x0b, 0x05, 0x39, 0xe6, 0x17,
   392  		0x21, 0x3a, 0x9a, 0x71, 0x51, 0x21, 0x5a, 0x1b,
   393  		// Match ID 32 bytes
   394  		0x6e, 0xa1, 0x22, 0x7b, 0x03, 0xd7, 0xbf, 0x05, 0xce, 0x1e, 0x23, 0xf3,
   395  		0xed, 0xf5, 0x73, 0x68, 0xf6, 0x9b, 0xa9, 0xee, 0x0c, 0xc0, 0x69, 0xf0,
   396  		0x9a, 0xb0, 0x95, 0x2a, 0x36, 0xd9, 0x64, 0xc5,
   397  		// Coin ID, 36 Bytes
   398  		0x28, 0xcb, 0x86, 0xe6, 0x78, 0xf6, 0x47, 0xcc, 0x88, 0xda, 0x73, 0x4e,
   399  		0xed, 0x11, 0x28, 0x6d, 0xab, 0x18, 0xb8, 0x48, 0x3f, 0xeb, 0x04, 0x58,
   400  		0x0e, 0x3c, 0xbc, 0x90, 0x55, 0x5a, 0x00, 0x47, 0x00, 0x00, 0x00, 0x05,
   401  		// Timestamp 8 bytes
   402  		0x00, 0x00, 0x00, 0x00, 0x5d, 0x9f, 0x15, 0x92,
   403  	}
   404  
   405  	b := redeem.Serialize()
   406  	if !bytes.Equal(b, exp) {
   407  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   408  	}
   409  
   410  	redeemB, err := json.Marshal(redeem)
   411  	if err != nil {
   412  		t.Fatalf("marshal error: %v", err)
   413  	}
   414  
   415  	var redeemBack Redemption
   416  	err = json.Unmarshal(redeemB, &redeemBack)
   417  	if err != nil {
   418  		t.Fatalf("unmarshal error: %v", err)
   419  	}
   420  
   421  	if !bytes.Equal(redeemBack.MatchID, redeem.MatchID) {
   422  		t.Fatal(redeemBack.MatchID, redeem.MatchID)
   423  	}
   424  	if !bytes.Equal(redeemBack.OrderID, redeem.OrderID) {
   425  		t.Fatal(redeemBack.OrderID, redeem.OrderID)
   426  	}
   427  	if !bytes.Equal(redeemBack.CoinID, redeem.CoinID) {
   428  		t.Fatal(redeemBack.CoinID, redeem.CoinID)
   429  	}
   430  	if redeemBack.Time != redeem.Time {
   431  		t.Fatal(redeemBack.Time, redeem.Time)
   432  	}
   433  }
   434  
   435  func TestPrefix(t *testing.T) {
   436  	// serialization: account ID (32) + base asset (4) + quote asset (4) +
   437  	// order type (1), client time (8), server time (8) = 57 bytes
   438  	acctID, _ := hex.DecodeString("05bf0f2b97fa551375b9c92687f7a948a8f4a4237653a04e6b00c6f14c72fd1e")
   439  	commit := []byte{
   440  		0xd9, 0x83, 0xec, 0xdf, 0x34, 0x0f, 0xd9, 0xaf, 0xda, 0xb8, 0x81,
   441  		0x8d, 0x5a, 0x29, 0x36, 0xe0, 0x71, 0xaf, 0x3c, 0xbb, 0x3d, 0xa8,
   442  		0xac, 0xf4, 0x38, 0xb6, 0xc2, 0x91, 0x65, 0xf2, 0x0d, 0x8d,
   443  	}
   444  	prefix := &Prefix{
   445  		AccountID:  acctID,
   446  		Base:       256,
   447  		Quote:      65536,
   448  		OrderType:  1,
   449  		ClientTime: 1571871297,
   450  		ServerTime: 1571871841,
   451  		Commit:     commit,
   452  	}
   453  
   454  	exp := []byte{
   455  		// Account ID 32 bytes
   456  		0x05, 0xbf, 0x0f, 0x2b, 0x97, 0xfa, 0x55, 0x13, 0x75, 0xb9, 0xc9, 0x26,
   457  		0x87, 0xf7, 0xa9, 0x48, 0xa8, 0xf4, 0xa4, 0x23, 0x76, 0x53, 0xa0, 0x4e,
   458  		0x6b, 0x00, 0xc6, 0xf1, 0x4c, 0x72, 0xfd, 0x1e,
   459  		// Base Asset 4 bytes
   460  		0x00, 0x00, 0x01, 0x00,
   461  		// Quote Asset 4 bytes
   462  		0x00, 0x01, 0x00, 0x00,
   463  		// Order Type 1 bytes
   464  		0x01,
   465  		// Client Time 8 bytes
   466  		0x00, 0x00, 0x00, 0x00, 0x5d, 0xb0, 0xda, 0x41,
   467  		// Server Time 8 bytes (zeros for client signature)
   468  		0x00, 0x00, 0x00, 0x00, 0x5d, 0xb0, 0xdc, 0x61,
   469  		// Commitment
   470  		0xd9, 0x83, 0xec, 0xdf, 0x34, 0x0f, 0xd9, 0xaf, 0xda, 0xb8, 0x81,
   471  		0x8d, 0x5a, 0x29, 0x36, 0xe0, 0x71, 0xaf, 0x3c, 0xbb, 0x3d, 0xa8,
   472  		0xac, 0xf4, 0x38, 0xb6, 0xc2, 0x91, 0x65, 0xf2, 0x0d, 0x8d,
   473  	}
   474  
   475  	b := prefix.Serialize()
   476  	if !bytes.Equal(b, exp) {
   477  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   478  	}
   479  
   480  	prefixB, err := json.Marshal(prefix)
   481  	if err != nil {
   482  		t.Fatalf("marshal error: %v", err)
   483  	}
   484  
   485  	var prefixBack Prefix
   486  	err = json.Unmarshal(prefixB, &prefixBack)
   487  	if err != nil {
   488  		t.Fatalf("unmarshal error: %v", err)
   489  	}
   490  	if !bytes.Equal(prefixBack.AccountID, prefix.AccountID) {
   491  		t.Fatalf("wrong account id. wanted %d, got %d", prefix.AccountID, prefixBack.AccountID)
   492  	}
   493  	if prefixBack.Base != prefix.Base {
   494  		t.Fatalf("wrong base asset. wanted %d, got %d", prefix.Base, prefixBack.Base)
   495  	}
   496  	if prefixBack.Quote != prefix.Quote {
   497  		t.Fatalf("wrong quote asset. wanted %d, got %d", prefix.Quote, prefixBack.Quote)
   498  	}
   499  	if prefixBack.OrderType != prefix.OrderType {
   500  		t.Fatalf("wrong order type. wanted %d, got %d", prefix.OrderType, prefixBack.OrderType)
   501  	}
   502  	if prefixBack.ClientTime != prefix.ClientTime {
   503  		t.Fatalf("wrong client time. wanted %d, got %d", prefix.ClientTime, prefixBack.ClientTime)
   504  	}
   505  	if prefixBack.ServerTime != prefix.ServerTime {
   506  		t.Fatalf("wrong server time. wanted %d, got %d", prefix.ServerTime, prefixBack.ServerTime)
   507  	}
   508  	if !bytes.Equal(prefixBack.Commit, prefix.Commit) {
   509  		t.Fatalf("wrong commitment. wanted %d, got %d", prefix.Commit, prefixBack.Commit)
   510  	}
   511  }
   512  
   513  func TestTrade(t *testing.T) {
   514  	// serialization: coin count (1), coin IDs (36*count), side (1), qty (8)
   515  	// = 10 + 36*count
   516  
   517  	addr := "13DePXLAKNsFCSmgfrEsYm8G1aCVZdYvP9"
   518  	coin1 := randomCoin()
   519  	coin2 := randomCoin()
   520  
   521  	trade := &Trade{
   522  		Side:     1,
   523  		Quantity: 600_000_000,
   524  		Coins:    []*Coin{coin1, coin2},
   525  		Address:  addr,
   526  	}
   527  
   528  	// Coin count
   529  	b := trade.Serialize()
   530  	if b[0] != 0x02 {
   531  		t.Fatalf("coin count byte incorrect: %d", b[0])
   532  	}
   533  	b = b[1:]
   534  
   535  	// first coin
   536  	cLen := len(coin1.ID)
   537  	if !bytes.Equal(b[:cLen], coin1.ID) {
   538  		t.Fatal(b[:cLen], coin1.ID)
   539  	}
   540  	b = b[cLen:]
   541  
   542  	// second coin
   543  	cLen = len(coin2.ID)
   544  	if !bytes.Equal(b[:cLen], coin2.ID) {
   545  		t.Fatal(b[:cLen], coin2.ID)
   546  	}
   547  	b = b[cLen:]
   548  
   549  	// side
   550  	if b[0] != 0x01 {
   551  		t.Fatalf("wrong side. wanted 1, got %d", b[0])
   552  	}
   553  	b = b[1:]
   554  
   555  	qty := []byte{0x00, 0x00, 0x00, 0x00, 0x23, 0xc3, 0x46, 0x00}
   556  	if !bytes.Equal(b, qty) {
   557  		t.Fatal(b, qty)
   558  	}
   559  }
   560  
   561  func TestLimit(t *testing.T) {
   562  	// serialization: prefix (105) + trade (variable) + address (~35)
   563  	// = 140 + len(trade)
   564  	prefix := &Prefix{
   565  		AccountID:  randomBytes(32),
   566  		Base:       256,
   567  		Quote:      65536,
   568  		OrderType:  1,
   569  		ClientTime: 1571874397,
   570  		ServerTime: 1571874405,
   571  		Commit:     randomBytes(32),
   572  	}
   573  	addr := "DsDePXLAKNsFCSmgfrEsYm8G1aCVZdYvP9"
   574  	coin1 := randomCoin()
   575  	coin2 := randomCoin()
   576  	trade := &Trade{
   577  		Side:     1,
   578  		Quantity: 600_000_000,
   579  		Coins:    []*Coin{coin1, coin2},
   580  		Address:  addr,
   581  	}
   582  	limit := &LimitOrder{
   583  		Prefix: *prefix,
   584  		Trade:  *trade,
   585  		Rate:   350_000_000,
   586  		TiF:    1,
   587  	}
   588  
   589  	b := limit.Serialize()
   590  
   591  	// Compare the prefix byte-for-byte and pop it from the front.
   592  	x := prefix.Serialize()
   593  	xLen := len(x)
   594  	if !bytes.Equal(b[:xLen], x) {
   595  		t.Fatal(x, b[:xLen])
   596  	}
   597  	b = b[xLen:]
   598  
   599  	// Compare the trade byte-for-byte and pop it from the front.
   600  	x = trade.Serialize()
   601  	xLen = len(x)
   602  	if !bytes.Equal(b[:xLen], x) {
   603  		t.Fatal(x, b[:xLen])
   604  	}
   605  	b = b[xLen:]
   606  
   607  	exp := []byte{
   608  		// Rate 8 bytes
   609  		0x00, 0x00, 0x00, 0x00, 0x14, 0xdc, 0x93, 0x80,
   610  		// Time-in-force 1 byte
   611  		0x01,
   612  		// Address 35 bytes
   613  		0x44, 0x73, 0x44, 0x65, 0x50, 0x58, 0x4c, 0x41, 0x4b, 0x4e, 0x73, 0x46,
   614  		0x43, 0x53, 0x6d, 0x67, 0x66, 0x72, 0x45, 0x73, 0x59, 0x6d, 0x38, 0x47,
   615  		0x31, 0x61, 0x43, 0x56, 0x5a, 0x64, 0x59, 0x76, 0x50, 0x39,
   616  	}
   617  	if !bytes.Equal(exp, b) {
   618  		t.Fatal(exp, b)
   619  	}
   620  
   621  	limitB, err := json.Marshal(limit)
   622  	if err != nil {
   623  		t.Fatalf("marshal error: %v", err)
   624  	}
   625  
   626  	var limitBack LimitOrder
   627  	err = json.Unmarshal(limitB, &limitBack)
   628  	if err != nil {
   629  		t.Fatalf("unmarshal error: %v", err)
   630  	}
   631  	comparePrefix(t, &limitBack.Prefix, &limit.Prefix)
   632  	compareTrade(t, &limitBack.Trade, &limit.Trade)
   633  	if limitBack.Rate != limit.Rate {
   634  		t.Fatal(limitBack.Rate, limit.Rate)
   635  	}
   636  	if limitBack.TiF != limit.TiF {
   637  		t.Fatal(limitBack.TiF, limit.TiF)
   638  	}
   639  }
   640  
   641  func TestMarket(t *testing.T) {
   642  	// serialization: prefix (105) + trade (variable) + rate (8)
   643  	// + time-in-force (1) + address (~35) = 149 + len(trade)
   644  	prefix := &Prefix{
   645  		AccountID:  randomBytes(32),
   646  		Base:       256,
   647  		Quote:      65536,
   648  		OrderType:  1,
   649  		ClientTime: 1571874397,
   650  		ServerTime: 1571874405,
   651  		Commit:     randomBytes(32),
   652  	}
   653  	addr := "16brznLu4ieZ6tToKfUgibD94UcqshGUE3"
   654  	coin1 := randomCoin()
   655  	coin2 := randomCoin()
   656  	trade := &Trade{
   657  		Side:     1,
   658  		Quantity: 600_000_000,
   659  		Coins:    []*Coin{coin1, coin2},
   660  		Address:  addr,
   661  	}
   662  	market := &MarketOrder{
   663  		Prefix: *prefix,
   664  		Trade:  *trade,
   665  	}
   666  
   667  	b := market.Serialize()
   668  
   669  	// Compare the prefix byte-for-byte and pop it from the front.
   670  	x := prefix.Serialize()
   671  	xLen := len(x)
   672  	if !bytes.Equal(b[:xLen], x) {
   673  		t.Fatal(x, b[:xLen])
   674  	}
   675  	b = b[xLen:]
   676  
   677  	// Compare the trade data byte-for-byte and pop it from the front.
   678  	x = trade.Serialize()
   679  	xLen = len(x)
   680  	if !bytes.Equal(b[:xLen], x) {
   681  		t.Fatal(x, b[:xLen])
   682  	}
   683  	b = b[xLen:]
   684  
   685  	// The only thing left should be the utf-8 encoded address.
   686  	addrBytes := []byte{
   687  		0x31, 0x36, 0x62, 0x72, 0x7a, 0x6e, 0x4c, 0x75, 0x34, 0x69, 0x65, 0x5a,
   688  		0x36, 0x74, 0x54, 0x6f, 0x4b, 0x66, 0x55, 0x67, 0x69, 0x62, 0x44, 0x39,
   689  		0x34, 0x55, 0x63, 0x71, 0x73, 0x68, 0x47, 0x55, 0x45, 0x33,
   690  	}
   691  	if !bytes.Equal(b, addrBytes) {
   692  		t.Fatal(b, addrBytes)
   693  	}
   694  
   695  	marketB, err := json.Marshal(market)
   696  	if err != nil {
   697  		t.Fatalf("marshal error: %v", err)
   698  	}
   699  
   700  	var marketBack MarketOrder
   701  	err = json.Unmarshal(marketB, &marketBack)
   702  	if err != nil {
   703  		t.Fatalf("unmarshal error: %v", err)
   704  	}
   705  
   706  	comparePrefix(t, &marketBack.Prefix, &market.Prefix)
   707  	compareTrade(t, &marketBack.Trade, &market.Trade)
   708  }
   709  
   710  func TestCancel(t *testing.T) {
   711  	// serialization: prefix (105) + target id (32) = 137
   712  	prefix := &Prefix{
   713  		AccountID:  randomBytes(32),
   714  		Base:       256,
   715  		Quote:      65536,
   716  		OrderType:  1,
   717  		ClientTime: 1571874397,
   718  		ServerTime: 1571874405,
   719  		Commit:     randomBytes(32),
   720  	}
   721  	targetID, _ := hex.DecodeString("a1f1b66916353b58dbb65562eb19731953b2f1215987a9d9137f0df3458637b7")
   722  	cancel := &CancelOrder{
   723  		Prefix:   *prefix,
   724  		TargetID: targetID,
   725  	}
   726  
   727  	b := cancel.Serialize()
   728  
   729  	// Compare the prefix byte-for-byte and pop it from the front.
   730  	x := prefix.Serialize()
   731  	xLen := len(x)
   732  	if !bytes.Equal(x, b[:xLen]) {
   733  		t.Fatal(x, b[:xLen])
   734  	}
   735  	b = b[xLen:]
   736  
   737  	target := []byte{
   738  		0xa1, 0xf1, 0xb6, 0x69, 0x16, 0x35, 0x3b, 0x58, 0xdb, 0xb6, 0x55, 0x62,
   739  		0xeb, 0x19, 0x73, 0x19, 0x53, 0xb2, 0xf1, 0x21, 0x59, 0x87, 0xa9, 0xd9,
   740  		0x13, 0x7f, 0x0d, 0xf3, 0x45, 0x86, 0x37, 0xb7,
   741  	}
   742  	if !bytes.Equal(b, target) {
   743  		t.Fatal(b, target)
   744  	}
   745  
   746  	cancelB, err := json.Marshal(cancel)
   747  	if err != nil {
   748  		t.Fatalf("marshal error: %v", err)
   749  	}
   750  
   751  	var cancelBack CancelOrder
   752  	err = json.Unmarshal(cancelB, &cancelBack)
   753  	if err != nil {
   754  		t.Fatalf("unmarshal error: %v", err)
   755  	}
   756  
   757  	comparePrefix(t, &cancelBack.Prefix, &cancel.Prefix)
   758  	if !bytes.Equal(cancelBack.TargetID, cancel.TargetID) {
   759  		t.Fatal(cancelBack.TargetID, cancel.TargetID)
   760  	}
   761  }
   762  
   763  func TestConnect(t *testing.T) {
   764  	// serialization: account ID (32) + api version (2) + timestamp (8) = 42 bytes
   765  	acctID, _ := hex.DecodeString("14ae3cbc703587122d68ac6fa9194dfdc8466fb5dec9f47d2805374adff3e016")
   766  	connect := &Connect{
   767  		AccountID:  acctID,
   768  		APIVersion: uint16(1),
   769  		Time:       uint64(1571575096),
   770  	}
   771  
   772  	exp := []byte{
   773  		// Account ID 32 bytes
   774  		0x14, 0xae, 0x3c, 0xbc, 0x70, 0x35, 0x87, 0x12, 0x2d, 0x68, 0xac, 0x6f,
   775  		0xa9, 0x19, 0x4d, 0xfd, 0xc8, 0x46, 0x6f, 0xb5, 0xde, 0xc9, 0xf4, 0x7d,
   776  		0x28, 0x05, 0x37, 0x4a, 0xdf, 0xf3, 0xe0, 0x16,
   777  		// API Version 2 bytes
   778  		0x00, 0x01,
   779  		// Time 8 bytes
   780  		0x00, 0x00, 0x00, 0x00, 0x5d, 0xac, 0x55, 0x38,
   781  	}
   782  
   783  	b := connect.Serialize()
   784  	if !bytes.Equal(b, exp) {
   785  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   786  	}
   787  
   788  	connectB, err := json.Marshal(connect)
   789  	if err != nil {
   790  		t.Fatalf("marshal error: %v", err)
   791  	}
   792  
   793  	var connectBack Connect
   794  	err = json.Unmarshal(connectB, &connectBack)
   795  	if err != nil {
   796  		t.Fatalf("unmarshal error: %v", err)
   797  	}
   798  
   799  	if !bytes.Equal(connectBack.AccountID, connect.AccountID) {
   800  		t.Fatal(connectBack.AccountID, connect.AccountID)
   801  	}
   802  	if connectBack.APIVersion != connect.APIVersion {
   803  		t.Fatal(connectBack.APIVersion, connect.APIVersion)
   804  	}
   805  	if connectBack.Time != connect.Time {
   806  		t.Fatal(connectBack.Time, connect.Time)
   807  	}
   808  }
   809  
   810  func TestPenalty(t *testing.T) {
   811  	// serialization: rule(1) + time (8) + duration (8) + details (variable, ~100) = 117 bytes
   812  	penalty := &Penalty{
   813  		Rule:    account.Rule(1),
   814  		Time:    uint64(1598929305),
   815  		Details: "You may no longer trade. Leave your client running to finish pending trades.",
   816  	}
   817  	penaltyNote := &PenaltyNote{Penalty: penalty}
   818  
   819  	exp := []byte{
   820  		// Rule 1 byte.
   821  		0x01,
   822  		// Time 8 bytes.
   823  		0x00, 0x00, 0x00, 0x00, 0x5f, 0x4d, 0xb9, 0x99,
   824  		// Details 76 bytes.
   825  		0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6e, 0x6f,
   826  		0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x74, 0x72,
   827  		0x61, 0x64, 0x65, 0x2e, 0x20, 0x4c, 0x65, 0x61, 0x76, 0x65,
   828  		0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x65,
   829  		0x6e, 0x74, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67,
   830  		0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68,
   831  		0x20, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74,
   832  		0x72, 0x61, 0x64, 0x65, 0x73, 0x2e,
   833  	}
   834  
   835  	b := penaltyNote.Serialize()
   836  	if !bytes.Equal(b, exp) {
   837  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   838  	}
   839  
   840  	penaltyB, err := json.Marshal(penalty)
   841  	if err != nil {
   842  		t.Fatalf("marshal error: %v", err)
   843  	}
   844  
   845  	var penaltyBack Penalty
   846  	err = json.Unmarshal(penaltyB, &penaltyBack)
   847  	if err != nil {
   848  		t.Fatalf("unmarshal error: %v", err)
   849  	}
   850  
   851  	if penaltyBack.Rule != penalty.Rule {
   852  		t.Fatal(penaltyBack.Rule, penalty.Rule)
   853  	}
   854  	if penaltyBack.Time != penalty.Time {
   855  		t.Fatal(penaltyBack.Time, penalty.Time)
   856  	}
   857  	if penaltyBack.Details != penalty.Details {
   858  		t.Fatal(penaltyBack.Details, penalty.Details)
   859  	}
   860  }
   861  
   862  func TestRegister(t *testing.T) {
   863  	// serialization: pubkey (33) + time (8) = 41
   864  	pk, _ := hex.DecodeString("f06e5cf13fc6debb8b90776da6624991ba50a11e784efed53d0a81c3be98397982")
   865  	register := &Register{
   866  		PubKey: pk,
   867  		Time:   uint64(1571700077),
   868  	}
   869  
   870  	exp := []byte{
   871  		// PubKey 33 bytes
   872  		0xf0, 0x6e, 0x5c, 0xf1, 0x3f, 0xc6, 0xde, 0xbb, 0x8b, 0x90, 0x77, 0x6d,
   873  		0xa6, 0x62, 0x49, 0x91, 0xba, 0x50, 0xa1, 0x1e, 0x78, 0x4e, 0xfe, 0xd5,
   874  		0x3d, 0x0a, 0x81, 0xc3, 0xbe, 0x98, 0x39, 0x79, 0x82,
   875  		// Time 8 bytes
   876  		0x00, 0x00, 0x00, 0x00, 0x5d, 0xae, 0x3d, 0x6d,
   877  	}
   878  
   879  	b := register.Serialize()
   880  	if !bytes.Equal(b, exp) {
   881  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   882  	}
   883  
   884  	registerB, err := json.Marshal(register)
   885  	if err != nil {
   886  		t.Fatalf("marshal error: %v", err)
   887  	}
   888  
   889  	var registerBack Register
   890  	err = json.Unmarshal(registerB, &registerBack)
   891  	if err != nil {
   892  		t.Fatalf("unmarshal error: %v", err)
   893  	}
   894  
   895  	if !bytes.Equal(registerBack.PubKey, register.PubKey) {
   896  		t.Fatal(registerBack.PubKey, register.PubKey)
   897  	}
   898  	if registerBack.Time != register.Time {
   899  		t.Fatal(registerBack.Time, register.Time)
   900  	}
   901  }
   902  
   903  func TestNotifyFee(t *testing.T) {
   904  	// serialization: account id (32) + txid (32) + vout (4) = 68
   905  	acctID, _ := hex.DecodeString("bd3faf7353b8fc40618527687b3ef99d00da480e354f2c4986479e2da626acf5")
   906  	coinid, _ := hex.DecodeString("51891f751b0dd987c0b8ff1703cd0dd3e2712847f4bdbc268c9656dc80d233c7")
   907  	notify := &NotifyFee{
   908  		AccountID: acctID,
   909  		CoinID:    coinid,
   910  		Time:      1571704611,
   911  	}
   912  
   913  	exp := []byte{
   914  		// Account ID 32 bytes
   915  		0xbd, 0x3f, 0xaf, 0x73, 0x53, 0xb8, 0xfc, 0x40, 0x61, 0x85, 0x27, 0x68,
   916  		0x7b, 0x3e, 0xf9, 0x9d, 0x00, 0xda, 0x48, 0x0e, 0x35, 0x4f, 0x2c, 0x49,
   917  		0x86, 0x47, 0x9e, 0x2d, 0xa6, 0x26, 0xac, 0xf5,
   918  		// Tx ID 32 bytes
   919  		0x51, 0x89, 0x1f, 0x75, 0x1b, 0x0d, 0xd9, 0x87, 0xc0, 0xb8, 0xff, 0x17,
   920  		0x03, 0xcd, 0x0d, 0xd3, 0xe2, 0x71, 0x28, 0x47, 0xf4, 0xbd, 0xbc, 0x26,
   921  		0x8c, 0x96, 0x56, 0xdc, 0x80, 0xd2, 0x33, 0xc7,
   922  		// Time 8 bytes
   923  		0x00, 0x00, 0x00, 0x00, 0x5d, 0xae, 0x4f, 0x23,
   924  	}
   925  
   926  	b := notify.Serialize()
   927  	if !bytes.Equal(b, exp) {
   928  		t.Fatalf("unexpected serialization. Wanted %x, got %x", exp, b)
   929  	}
   930  
   931  	notifyB, err := json.Marshal(notify)
   932  	if err != nil {
   933  		t.Fatalf("marshal error: %v", err)
   934  	}
   935  
   936  	var notifyBack NotifyFee
   937  	err = json.Unmarshal(notifyB, &notifyBack)
   938  	if err != nil {
   939  		t.Fatalf("unmarshal error: %v", err)
   940  	}
   941  
   942  	if !bytes.Equal(notifyBack.AccountID, notify.AccountID) {
   943  		t.Fatal(notifyBack.AccountID, notify.AccountID)
   944  	}
   945  	if !bytes.Equal(notifyBack.CoinID, notify.CoinID) {
   946  		t.Fatal(notifyBack.CoinID, notify.CoinID)
   947  	}
   948  	if notifyBack.Time != notify.Time {
   949  		t.Fatal(notifyBack.Time, notify.Time)
   950  	}
   951  }
   952  
   953  func TestSignable(t *testing.T) {
   954  	sig := []byte{
   955  		0x07, 0xad, 0x7f, 0x33, 0xc5, 0xb0, 0x13, 0xa1, 0xbb, 0xd6, 0xad, 0xc0,
   956  		0xd2, 0x16, 0xd8, 0x93, 0x8c, 0x73, 0x64, 0xe5, 0x6a, 0x17, 0x8c, 0x7a,
   957  		0x17, 0xa9, 0xe7, 0x47, 0xad, 0x55, 0xaf, 0xe6, 0x55, 0x2b, 0xb2, 0x76,
   958  		0xf8, 0x8e, 0x34, 0x2e, 0x56, 0xac, 0xaa, 0x8a, 0x52, 0x41, 0x2e, 0x51,
   959  		0x8b, 0x0f, 0xe6, 0xb2, 0x2a, 0x21, 0x77, 0x9a, 0x76, 0x99, 0xa5, 0xe5,
   960  		0x39, 0xa8, 0xa1, 0xdd, 0x1d, 0x49, 0x8b, 0xb0, 0x16, 0xf7, 0x18, 0x70,
   961  	}
   962  	s := Signature{}
   963  	s.SetSig(sig)
   964  	if !bytes.Equal(sig, s.SigBytes()) {
   965  		t.Fatalf("signatures not equal")
   966  	}
   967  }
   968  
   969  func TestBytes(t *testing.T) {
   970  	rawB := []byte{0xfc, 0xf6, 0xd9, 0xb9, 0xdb, 0x10, 0x4c, 0xc0, 0x13, 0x3a}
   971  	hexB := "fcf6d9b9db104cc0133a"
   972  
   973  	type byter struct {
   974  		B Bytes `json:"b"`
   975  	}
   976  
   977  	b := byter{}
   978  	js := `{"b":"` + hexB + `"}`
   979  	err := json.Unmarshal([]byte(js), &b)
   980  	if err != nil {
   981  		t.Fatalf("unmarshal error: %v", err)
   982  	}
   983  
   984  	if !bytes.Equal(rawB, b.B) {
   985  		t.Fatalf("unmarshalled Bytes not correct. wanted %x, got %x.", rawB, b.B)
   986  	}
   987  
   988  	marshalled, err := json.Marshal(b)
   989  	if err != nil {
   990  		t.Fatalf("marshal error: %v", err)
   991  	}
   992  	if string(marshalled) != js {
   993  		t.Fatalf("marshalled Bytes not correct. wanted %s, got %s", js, string(marshalled))
   994  	}
   995  
   996  	fromHex, _ := hex.DecodeString(hexB)
   997  	if !bytes.Equal(rawB, fromHex) {
   998  		t.Fatalf("hex-constructed Bytes not correct. wanted %x, got %x.", rawB, fromHex)
   999  	}
  1000  }
  1001  
  1002  func TestDecodeMessage(t *testing.T) {
  1003  	msg, err := DecodeMessage([]byte(`{"type":1,"route":"testroute","id":5,"payload":10}`))
  1004  	if err != nil {
  1005  		t.Fatalf("error decoding json message: %v", err)
  1006  	}
  1007  	if msg.Type != 1 {
  1008  		t.Fatalf("wrong message type. wanted 1, got %d", msg.Type)
  1009  	}
  1010  	if msg.Route != "testroute" {
  1011  		t.Fatalf("wrong message type. wanted 'testroute', got '%s'", msg.Route)
  1012  	}
  1013  	if msg.ID != 5 {
  1014  		t.Fatalf("wrong message type. wanted 5, got %d", msg.ID)
  1015  	}
  1016  	if string(msg.Payload) != "10" {
  1017  		t.Fatalf("wrong payload. wanted '10, got '%s'", string(msg.Payload))
  1018  	}
  1019  	// Test invalid json
  1020  	_, err = DecodeMessage([]byte(`{"type":?}`))
  1021  	if err == nil {
  1022  		t.Fatalf("no json decode error for invalid json")
  1023  	}
  1024  }
  1025  
  1026  func TestRespReq(t *testing.T) {
  1027  	// Test invalid json result.
  1028  	_, err := NewResponse(5, make(chan int), nil)
  1029  	if err == nil {
  1030  		t.Fatalf("no error for invalid json")
  1031  	}
  1032  	// Zero ID not valid.
  1033  	_, err = NewResponse(0, 10, nil)
  1034  	if err == nil {
  1035  		t.Fatalf("no error for id = 0")
  1036  	}
  1037  	msg, err := NewResponse(5, 10, nil)
  1038  	if err != nil {
  1039  		t.Fatalf("NewResponse error: %v", err)
  1040  	}
  1041  	if msg.ID != 5 {
  1042  		t.Fatalf("wrong message ID. wanted 5, got ")
  1043  	}
  1044  	resp, err := msg.Response()
  1045  	if err != nil {
  1046  		t.Fatalf("error getting response payload: %v", err)
  1047  	}
  1048  	if resp.Error != nil {
  1049  		t.Fatalf("unexpected error making success response")
  1050  	}
  1051  	if string(resp.Result) != "10" {
  1052  		t.Fatalf("unexpected result. wanted '10', got '%s'", string(resp.Result))
  1053  	}
  1054  
  1055  	// Check error.
  1056  	msg, err = NewResponse(5, nil, NewError(15, "testmsg"))
  1057  	if err != nil {
  1058  		t.Fatalf("unexpected error making error response")
  1059  	}
  1060  	_, err = msg.Response()
  1061  	if err != nil {
  1062  		t.Fatalf("unexpected error getting error response payload: %v", err)
  1063  	}
  1064  
  1065  	// Test Requests
  1066  	_, err = NewRequest(5, "testroute", make(chan int))
  1067  	if err == nil {
  1068  		t.Fatalf("no error for invalid json type request payload")
  1069  	}
  1070  	_, err = NewRequest(0, "testroute", 10)
  1071  	if err == nil {
  1072  		t.Fatalf("no error id = 0 request")
  1073  	}
  1074  	_, err = NewRequest(5, "", 10)
  1075  	if err == nil {
  1076  		t.Fatalf("no error for empty string route request")
  1077  	}
  1078  	msg, err = NewRequest(5, "testroute", 10)
  1079  	if err != nil {
  1080  		t.Fatalf("error for valid request payload: %v", err)
  1081  	}
  1082  	// A Request-type Message should error if trying to retrieve the
  1083  	// ResponsePayload
  1084  	_, err = msg.Response()
  1085  	if err == nil {
  1086  		t.Fatalf("no error when retrieving response payload from request-type message")
  1087  	}
  1088  
  1089  	// Test Notifications
  1090  	_, err = NewNotification("testroute", make(chan int))
  1091  	if err == nil {
  1092  		t.Fatalf("no error for invalid json type notification payload")
  1093  	}
  1094  	_, err = NewNotification("", 10)
  1095  	if err == nil {
  1096  		t.Fatalf("no error for empty string route request")
  1097  	}
  1098  	_, err = NewNotification("testroute", 10)
  1099  	if err != nil {
  1100  		t.Fatalf("error for valid request payload: %v", err)
  1101  	}
  1102  }
  1103  
  1104  func comparePrefix(t *testing.T, p1, p2 *Prefix) {
  1105  	if !bytes.Equal(p1.AccountID, p2.AccountID) {
  1106  		t.Fatal(p1.AccountID, p2.AccountID)
  1107  	}
  1108  	if p1.Base != p2.Base {
  1109  		t.Fatal(p1.Base, p2.Base)
  1110  	}
  1111  	if p1.Quote != p2.Quote {
  1112  		t.Fatal(p1.Quote, p2.Quote)
  1113  	}
  1114  	if p1.OrderType != p2.OrderType {
  1115  		t.Fatal(p1.OrderType, p2.OrderType)
  1116  	}
  1117  	if p1.ClientTime != p2.ClientTime {
  1118  		t.Fatal(p1.ClientTime, p2.ClientTime)
  1119  	}
  1120  	if p1.ServerTime != p2.ServerTime {
  1121  		t.Fatal(p1.ServerTime, p2.ServerTime)
  1122  	}
  1123  }
  1124  
  1125  func compareTrade(t *testing.T, t1, t2 *Trade) {
  1126  	if t1.Side != t2.Side {
  1127  		t.Fatal(t1.Side, t2.Side)
  1128  	}
  1129  	if t1.Quantity != t2.Quantity {
  1130  		t.Fatal(t1.Quantity, t2.Quantity)
  1131  	}
  1132  	if len(t1.Coins) != 2 {
  1133  		t.Fatalf("wrong number of coins. expected 2 got %d", len(t1.Coins))
  1134  	}
  1135  	if t1.Address != t2.Address {
  1136  		t.Fatal(t1.Address, t2.Address)
  1137  	}
  1138  }
  1139  
  1140  func randomBytes(len int) []byte {
  1141  	bytes := make([]byte, len)
  1142  	rand.Read(bytes)
  1143  	return bytes
  1144  }
  1145  
  1146  func randomCoin() *Coin {
  1147  	return &Coin{
  1148  		ID: randomBytes(36),
  1149  		// the rest are not part of the serialized coins.
  1150  		PubKeys: []Bytes{randomBytes(33)},
  1151  		Sigs:    []Bytes{randomBytes(77)},
  1152  		Redeem:  randomBytes(25),
  1153  	}
  1154  }