github.com/theQRL/go-zond@v0.2.1/signer/core/signed_data_test.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core_test
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/json"
    23  	"fmt"
    24  	"os"
    25  	"path"
    26  	"strings"
    27  	"testing"
    28  
    29  	"github.com/theQRL/go-zond/accounts/keystore"
    30  	"github.com/theQRL/go-zond/common"
    31  	"github.com/theQRL/go-zond/common/hexutil"
    32  	"github.com/theQRL/go-zond/common/math"
    33  	"github.com/theQRL/go-zond/crypto"
    34  	"github.com/theQRL/go-zond/signer/core"
    35  	"github.com/theQRL/go-zond/signer/core/apitypes"
    36  )
    37  
    38  var typesStandard = apitypes.Types{
    39  	"EIP712Domain": {
    40  		{
    41  			Name: "name",
    42  			Type: "string",
    43  		},
    44  		{
    45  			Name: "version",
    46  			Type: "string",
    47  		},
    48  		{
    49  			Name: "chainId",
    50  			Type: "uint256",
    51  		},
    52  		{
    53  			Name: "verifyingContract",
    54  			Type: "address",
    55  		},
    56  	},
    57  	"Person": {
    58  		{
    59  			Name: "name",
    60  			Type: "string",
    61  		},
    62  		{
    63  			Name: "wallet",
    64  			Type: "address",
    65  		},
    66  	},
    67  	"Mail": {
    68  		{
    69  			Name: "from",
    70  			Type: "Person",
    71  		},
    72  		{
    73  			Name: "to",
    74  			Type: "Person",
    75  		},
    76  		{
    77  			Name: "contents",
    78  			Type: "string",
    79  		},
    80  	},
    81  }
    82  
    83  var jsonTypedData = `
    84      {
    85        "types": {
    86          "EIP712Domain": [
    87            {
    88              "name": "name",
    89              "type": "string"
    90            },
    91            {
    92              "name": "version",
    93              "type": "string"
    94            },
    95            {
    96              "name": "chainId",
    97              "type": "uint256"
    98            },
    99            {
   100              "name": "verifyingContract",
   101              "type": "address"
   102            }
   103          ],
   104          "Person": [
   105            {
   106              "name": "name",
   107              "type": "string"
   108            },
   109            {
   110              "name": "test",
   111              "type": "uint8"
   112            },
   113            {
   114              "name": "wallet",
   115              "type": "address"
   116            }
   117          ],
   118          "Mail": [
   119            {
   120              "name": "from",
   121              "type": "Person"
   122            },
   123            {
   124              "name": "to",
   125              "type": "Person"
   126            },
   127            {
   128              "name": "contents",
   129              "type": "string"
   130            }
   131          ]
   132        },
   133        "primaryType": "Mail",
   134        "domain": {
   135          "name": "Ether Mail",
   136          "version": "1",
   137          "chainId": "1",
   138          "verifyingContract": "ZCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
   139        },
   140        "message": {
   141          "from": {
   142            "name": "Cow",
   143  		  "test": 3,
   144            "wallet": "ZcD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
   145          },
   146          "to": {
   147            "name": "Bob",
   148            "wallet": "ZbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
   149          },
   150          "contents": "Hello, Bob!"
   151        }
   152      }
   153  `
   154  
   155  const primaryType = "Mail"
   156  
   157  var domainStandard = apitypes.TypedDataDomain{
   158  	Name:              "Ether Mail",
   159  	Version:           "1",
   160  	ChainId:           math.NewHexOrDecimal256(1),
   161  	VerifyingContract: "ZCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
   162  	Salt:              "",
   163  }
   164  
   165  var messageStandard = map[string]interface{}{
   166  	"from": map[string]interface{}{
   167  		"name":   "Cow",
   168  		"wallet": "ZCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
   169  	},
   170  	"to": map[string]interface{}{
   171  		"name":   "Bob",
   172  		"wallet": "ZbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
   173  	},
   174  	"contents": "Hello, Bob!",
   175  }
   176  
   177  var typedData = apitypes.TypedData{
   178  	Types:       typesStandard,
   179  	PrimaryType: primaryType,
   180  	Domain:      domainStandard,
   181  	Message:     messageStandard,
   182  }
   183  
   184  func TestSignData(t *testing.T) {
   185  	api, control := setup(t)
   186  	//Create two accounts
   187  	createAccount(control, api, t)
   188  	createAccount(control, api, t)
   189  	control.approveCh <- "1"
   190  	list, err := api.List(context.Background())
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  	a := common.NewMixedcaseAddress(list[0])
   195  
   196  	control.approveCh <- "Y"
   197  	control.inputCh <- "wrongpassword"
   198  	signature, err := api.SignData(context.Background(), apitypes.TextPlain.Mime, a, hexutil.Encode([]byte("EHLO world")))
   199  	if signature != nil {
   200  		t.Errorf("Expected nil-data, got %x", signature)
   201  	}
   202  	if err != keystore.ErrDecrypt {
   203  		t.Errorf("Expected ErrLocked! '%v'", err)
   204  	}
   205  	control.approveCh <- "No way"
   206  	signature, err = api.SignData(context.Background(), apitypes.TextPlain.Mime, a, hexutil.Encode([]byte("EHLO world")))
   207  	if signature != nil {
   208  		t.Errorf("Expected nil-data, got %x", signature)
   209  	}
   210  	if err != core.ErrRequestDenied {
   211  		t.Errorf("Expected ErrRequestDenied! '%v'", err)
   212  	}
   213  	// text/plain
   214  	control.approveCh <- "Y"
   215  	control.inputCh <- "a_long_password"
   216  	signature, err = api.SignData(context.Background(), apitypes.TextPlain.Mime, a, hexutil.Encode([]byte("EHLO world")))
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if signature == nil || len(signature) != 4595 {
   221  		t.Errorf("Expected 65 byte signature (got %d bytes)", len(signature))
   222  	}
   223  	// data/typed via SignTypeData
   224  	control.approveCh <- "Y"
   225  	control.inputCh <- "a_long_password"
   226  	var want []byte
   227  	if signature, err = api.SignTypedData(context.Background(), a, typedData); err != nil {
   228  		t.Fatal(err)
   229  	} else if signature == nil || len(signature) != 4595 {
   230  		t.Errorf("Expected 65 byte signature (got %d bytes)", len(signature))
   231  	} else {
   232  		want = signature
   233  	}
   234  
   235  	// data/typed via SignData / mimetype typed data
   236  	control.approveCh <- "Y"
   237  	control.inputCh <- "a_long_password"
   238  	if typedDataJson, err := json.Marshal(typedData); err != nil {
   239  		t.Fatal(err)
   240  	} else if signature, err = api.SignData(context.Background(), apitypes.DataTyped.Mime, a, hexutil.Encode(typedDataJson)); err != nil {
   241  		t.Fatal(err)
   242  	} else if signature == nil || len(signature) != 4595 {
   243  		t.Errorf("Expected 65 byte signature (got %d bytes)", len(signature))
   244  	} else if have := signature; !bytes.Equal(have, want) {
   245  		t.Fatalf("want %x, have %x", want, have)
   246  	}
   247  }
   248  
   249  func TestDomainChainId(t *testing.T) {
   250  	withoutChainID := apitypes.TypedData{
   251  		Types: apitypes.Types{
   252  			"EIP712Domain": []apitypes.Type{
   253  				{Name: "name", Type: "string"},
   254  			},
   255  		},
   256  		Domain: apitypes.TypedDataDomain{
   257  			Name: "test",
   258  		},
   259  	}
   260  
   261  	if _, ok := withoutChainID.Domain.Map()["chainId"]; ok {
   262  		t.Errorf("Expected the chainId key to not be present in the domain map")
   263  	}
   264  	// should encode successfully
   265  	if _, err := withoutChainID.HashStruct("EIP712Domain", withoutChainID.Domain.Map()); err != nil {
   266  		t.Errorf("Expected the typedData to encode the domain successfully, got %v", err)
   267  	}
   268  	withChainID := apitypes.TypedData{
   269  		Types: apitypes.Types{
   270  			"EIP712Domain": []apitypes.Type{
   271  				{Name: "name", Type: "string"},
   272  				{Name: "chainId", Type: "uint256"},
   273  			},
   274  		},
   275  		Domain: apitypes.TypedDataDomain{
   276  			Name:    "test",
   277  			ChainId: math.NewHexOrDecimal256(1),
   278  		},
   279  	}
   280  
   281  	if _, ok := withChainID.Domain.Map()["chainId"]; !ok {
   282  		t.Errorf("Expected the chainId key be present in the domain map")
   283  	}
   284  	// should encode successfully
   285  	if _, err := withChainID.HashStruct("EIP712Domain", withChainID.Domain.Map()); err != nil {
   286  		t.Errorf("Expected the typedData to encode the domain successfully, got %v", err)
   287  	}
   288  }
   289  
   290  func TestHashStruct(t *testing.T) {
   291  	hash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
   292  	if err != nil {
   293  		t.Fatal(err)
   294  	}
   295  	mainHash := fmt.Sprintf("0x%s", common.Bytes2Hex(hash))
   296  	if mainHash != "0xc52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e" {
   297  		t.Errorf("Expected different hashStruct result (got %s)", mainHash)
   298  	}
   299  
   300  	hash, err = typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
   301  	if err != nil {
   302  		t.Error(err)
   303  	}
   304  	domainHash := fmt.Sprintf("0x%s", common.Bytes2Hex(hash))
   305  	if domainHash != "0xf2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f" {
   306  		t.Errorf("Expected different domain hashStruct result (got %s)", domainHash)
   307  	}
   308  }
   309  
   310  func TestEncodeType(t *testing.T) {
   311  	domainTypeEncoding := string(typedData.EncodeType("EIP712Domain"))
   312  	if domainTypeEncoding != "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" {
   313  		t.Errorf("Expected different encodeType result (got %s)", domainTypeEncoding)
   314  	}
   315  
   316  	mailTypeEncoding := string(typedData.EncodeType(typedData.PrimaryType))
   317  	if mailTypeEncoding != "Mail(Person from,Person to,string contents)Person(string name,address wallet)" {
   318  		t.Errorf("Expected different encodeType result (got %s)", mailTypeEncoding)
   319  	}
   320  }
   321  
   322  func TestTypeHash(t *testing.T) {
   323  	mailTypeHash := fmt.Sprintf("0x%s", common.Bytes2Hex(typedData.TypeHash(typedData.PrimaryType)))
   324  	if mailTypeHash != "0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2" {
   325  		t.Errorf("Expected different typeHash result (got %s)", mailTypeHash)
   326  	}
   327  }
   328  
   329  func TestEncodeData(t *testing.T) {
   330  	hash, err := typedData.EncodeData(typedData.PrimaryType, typedData.Message, 0)
   331  	if err != nil {
   332  		t.Fatal(err)
   333  	}
   334  	dataEncoding := fmt.Sprintf("0x%s", common.Bytes2Hex(hash))
   335  	if dataEncoding != "0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8" {
   336  		t.Errorf("Expected different encodeData result (got %s)", dataEncoding)
   337  	}
   338  }
   339  
   340  func TestFormatter(t *testing.T) {
   341  	var d apitypes.TypedData
   342  	err := json.Unmarshal([]byte(jsonTypedData), &d)
   343  	if err != nil {
   344  		t.Fatalf("unmarshalling failed '%v'", err)
   345  	}
   346  	formatted, _ := d.Format()
   347  	for _, item := range formatted {
   348  		t.Logf("'%v'\n", item.Pprint(0))
   349  	}
   350  
   351  	j, _ := json.Marshal(formatted)
   352  	t.Logf("'%v'\n", string(j))
   353  }
   354  
   355  func sign(typedData apitypes.TypedData) ([]byte, []byte, error) {
   356  	domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
   357  	if err != nil {
   358  		return nil, nil, err
   359  	}
   360  	typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
   361  	if err != nil {
   362  		return nil, nil, err
   363  	}
   364  	rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
   365  	sighash := crypto.Keccak256(rawData)
   366  	return typedDataHash, sighash, nil
   367  }
   368  
   369  func TestJsonFiles(t *testing.T) {
   370  	testfiles, err := os.ReadDir("testdata/")
   371  	if err != nil {
   372  		t.Fatalf("failed reading files: %v", err)
   373  	}
   374  	for i, fInfo := range testfiles {
   375  		if !strings.HasSuffix(fInfo.Name(), "json") {
   376  			continue
   377  		}
   378  		expectedFailure := strings.HasPrefix(fInfo.Name(), "expfail")
   379  		data, err := os.ReadFile(path.Join("testdata", fInfo.Name()))
   380  		if err != nil {
   381  			t.Errorf("Failed to read file %v: %v", fInfo.Name(), err)
   382  			continue
   383  		}
   384  		var typedData apitypes.TypedData
   385  		err = json.Unmarshal(data, &typedData)
   386  		if err != nil {
   387  			t.Errorf("Test %d, file %v, json unmarshalling failed: %v", i, fInfo.Name(), err)
   388  			continue
   389  		}
   390  		_, _, err = sign(typedData)
   391  		t.Logf("Error %v\n", err)
   392  		if err != nil && !expectedFailure {
   393  			t.Errorf("Test %d failed, file %v: %v", i, fInfo.Name(), err)
   394  		}
   395  		if expectedFailure && err == nil {
   396  			t.Errorf("Test %d succeeded (expected failure), file %v: %v", i, fInfo.Name(), err)
   397  		}
   398  	}
   399  }
   400  
   401  // TestFuzzerFiles tests some files that have been found by fuzzing to cause
   402  // crashes or hangs.
   403  func TestFuzzerFiles(t *testing.T) {
   404  	corpusdir := path.Join("testdata", "fuzzing")
   405  	testfiles, err := os.ReadDir(corpusdir)
   406  	if err != nil {
   407  		t.Fatalf("failed reading files: %v", err)
   408  	}
   409  	verbose := false
   410  	for i, fInfo := range testfiles {
   411  		data, err := os.ReadFile(path.Join(corpusdir, fInfo.Name()))
   412  		if err != nil {
   413  			t.Errorf("Failed to read file %v: %v", fInfo.Name(), err)
   414  			continue
   415  		}
   416  		var typedData apitypes.TypedData
   417  		err = json.Unmarshal(data, &typedData)
   418  		if err != nil {
   419  			t.Errorf("Test %d, file %v, json unmarshalling failed: %v", i, fInfo.Name(), err)
   420  			continue
   421  		}
   422  		_, err = typedData.EncodeData("EIP712Domain", typedData.Domain.Map(), 1)
   423  		if verbose && err != nil {
   424  			t.Logf("%d, EncodeData[1] err: %v\n", i, err)
   425  		}
   426  		_, err = typedData.EncodeData(typedData.PrimaryType, typedData.Message, 1)
   427  		if verbose && err != nil {
   428  			t.Logf("%d, EncodeData[2] err: %v\n", i, err)
   429  		}
   430  		typedData.Format()
   431  	}
   432  }
   433  
   434  var complexTypedData = `
   435  {
   436      "types": {
   437          "EIP712Domain": [
   438              {
   439                  "name": "chainId",
   440                  "type": "uint256"
   441              },
   442              {
   443                  "name": "name",
   444                  "type": "string"
   445              },
   446              {
   447                  "name": "verifyingContract",
   448                  "type": "address"
   449              },
   450              {
   451                  "name": "version",
   452                  "type": "string"
   453              }
   454          ],
   455          "Action": [
   456              {
   457                  "name": "action",
   458                  "type": "string"
   459              },
   460              {
   461                  "name": "params",
   462                  "type": "string"
   463              }
   464          ],
   465          "Cell": [
   466              {
   467                  "name": "capacity",
   468                  "type": "string"
   469              },
   470              {
   471                  "name": "lock",
   472                  "type": "string"
   473              },
   474              {
   475                  "name": "type",
   476                  "type": "string"
   477              },
   478              {
   479                  "name": "data",
   480                  "type": "string"
   481              },
   482              {
   483                  "name": "extraData",
   484                  "type": "string"
   485              }
   486          ],
   487          "Transaction": [
   488              {
   489                  "name": "DAS_MESSAGE",
   490                  "type": "string"
   491              },
   492              {
   493                  "name": "inputsCapacity",
   494                  "type": "string"
   495              },
   496              {
   497                  "name": "outputsCapacity",
   498                  "type": "string"
   499              },
   500              {
   501                  "name": "fee",
   502                  "type": "string"
   503              },
   504              {
   505                  "name": "action",
   506                  "type": "Action"
   507              },
   508              {
   509                  "name": "inputs",
   510                  "type": "Cell[]"
   511              },
   512              {
   513                  "name": "outputs",
   514                  "type": "Cell[]"
   515              },
   516              {
   517                  "name": "digest",
   518                  "type": "bytes32"
   519              }
   520          ]
   521      },
   522      "primaryType": "Transaction",
   523      "domain": {
   524          "chainId": "56",
   525          "name": "da.systems",
   526          "verifyingContract": "Z0000000000000000000000000000000020210722",
   527          "version": "1"
   528      },
   529      "message": {
   530          "DAS_MESSAGE": "SELL mobcion.bit FOR 100000 CKB",
   531          "inputsCapacity": "1216.9999 CKB",
   532          "outputsCapacity": "1216.9998 CKB",
   533          "fee": "0.0001 CKB",
   534          "digest": "0x53a6c0f19ec281604607f5d6817e442082ad1882bef0df64d84d3810dae561eb",
   535          "action": {
   536              "action": "start_account_sale",
   537              "params": "0x00"
   538          },
   539          "inputs": [
   540              {
   541                  "capacity": "218 CKB",
   542                  "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...",
   543                  "type": "account-cell-type,0x01,0x",
   544                  "data": "{ account: mobcion.bit, expired_at: 1670913958 }",
   545                  "extraData": "{ status: 0, records_hash: 0x55478d76900611eb079b22088081124ed6c8bae21a05dd1a0d197efcc7c114ce }"
   546              }
   547          ],
   548          "outputs": [
   549              {
   550                  "capacity": "218 CKB",
   551                  "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...",
   552                  "type": "account-cell-type,0x01,0x",
   553                  "data": "{ account: mobcion.bit, expired_at: 1670913958 }",
   554                  "extraData": "{ status: 1, records_hash: 0x55478d76900611eb079b22088081124ed6c8bae21a05dd1a0d197efcc7c114ce }"
   555              },
   556              {
   557                  "capacity": "201 CKB",
   558                  "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...",
   559                  "type": "account-sale-cell-type,0x01,0x",
   560                  "data": "0x1209460ef3cb5f1c68ed2c43a3e020eec2d9de6e...",
   561                  "extraData": ""
   562              }
   563          ]
   564      }
   565  }
   566  `
   567  
   568  func TestComplexTypedData(t *testing.T) {
   569  	var td apitypes.TypedData
   570  	err := json.Unmarshal([]byte(complexTypedData), &td)
   571  	if err != nil {
   572  		t.Fatalf("unmarshalling failed '%v'", err)
   573  	}
   574  	_, sighash, err := sign(td)
   575  	if err != nil {
   576  		t.Fatal(err)
   577  	}
   578  	expSigHash := common.FromHex("0x42b1aca82bb6900ff75e90a136de550a58f1a220a071704088eabd5e6ce20446")
   579  	if !bytes.Equal(expSigHash, sighash) {
   580  		t.Fatalf("Error, got %x, wanted %x", sighash, expSigHash)
   581  	}
   582  }
   583  
   584  var complexTypedDataLCRefType = `
   585  {
   586      "types": {
   587          "EIP712Domain": [
   588              {
   589                  "name": "chainId",
   590                  "type": "uint256"
   591              },
   592              {
   593                  "name": "name",
   594                  "type": "string"
   595              },
   596              {
   597                  "name": "verifyingContract",
   598                  "type": "address"
   599              },
   600              {
   601                  "name": "version",
   602                  "type": "string"
   603              }
   604          ],
   605          "Action": [
   606              {
   607                  "name": "action",
   608                  "type": "string"
   609              },
   610              {
   611                  "name": "params",
   612                  "type": "string"
   613              }
   614          ],
   615          "cCell": [
   616              {
   617                  "name": "capacity",
   618                  "type": "string"
   619              },
   620              {
   621                  "name": "lock",
   622                  "type": "string"
   623              },
   624              {
   625                  "name": "type",
   626                  "type": "string"
   627              },
   628              {
   629                  "name": "data",
   630                  "type": "string"
   631              },
   632              {
   633                  "name": "extraData",
   634                  "type": "string"
   635              }
   636          ],
   637          "Transaction": [
   638              {
   639                  "name": "DAS_MESSAGE",
   640                  "type": "string"
   641              },
   642              {
   643                  "name": "inputsCapacity",
   644                  "type": "string"
   645              },
   646              {
   647                  "name": "outputsCapacity",
   648                  "type": "string"
   649              },
   650              {
   651                  "name": "fee",
   652                  "type": "string"
   653              },
   654              {
   655                  "name": "action",
   656                  "type": "Action"
   657              },
   658              {
   659                  "name": "inputs",
   660                  "type": "cCell[]"
   661              },
   662              {
   663                  "name": "outputs",
   664                  "type": "cCell[]"
   665              },
   666              {
   667                  "name": "digest",
   668                  "type": "bytes32"
   669              }
   670          ]
   671      },
   672      "primaryType": "Transaction",
   673      "domain": {
   674          "chainId": "56",
   675          "name": "da.systems",
   676          "verifyingContract": "Z0000000000000000000000000000000020210722",
   677          "version": "1"
   678      },
   679      "message": {
   680          "DAS_MESSAGE": "SELL mobcion.bit FOR 100000 CKB",
   681          "inputsCapacity": "1216.9999 CKB",
   682          "outputsCapacity": "1216.9998 CKB",
   683          "fee": "0.0001 CKB",
   684          "digest": "0x53a6c0f19ec281604607f5d6817e442082ad1882bef0df64d84d3810dae561eb",
   685          "action": {
   686              "action": "start_account_sale",
   687              "params": "0x00"
   688          },
   689          "inputs": [
   690              {
   691                  "capacity": "218 CKB",
   692                  "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...",
   693                  "type": "account-cell-type,0x01,0x",
   694                  "data": "{ account: mobcion.bit, expired_at: 1670913958 }",
   695                  "extraData": "{ status: 0, records_hash: 0x55478d76900611eb079b22088081124ed6c8bae21a05dd1a0d197efcc7c114ce }"
   696              }
   697          ],
   698          "outputs": [
   699              {
   700                  "capacity": "218 CKB",
   701                  "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...",
   702                  "type": "account-cell-type,0x01,0x",
   703                  "data": "{ account: mobcion.bit, expired_at: 1670913958 }",
   704                  "extraData": "{ status: 1, records_hash: 0x55478d76900611eb079b22088081124ed6c8bae21a05dd1a0d197efcc7c114ce }"
   705              },
   706              {
   707                  "capacity": "201 CKB",
   708                  "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...",
   709                  "type": "account-sale-cell-type,0x01,0x",
   710                  "data": "0x1209460ef3cb5f1c68ed2c43a3e020eec2d9de6e...",
   711                  "extraData": ""
   712              }
   713          ]
   714      }
   715  }
   716  `
   717  
   718  func TestComplexTypedDataWithLowercaseReftype(t *testing.T) {
   719  	var td apitypes.TypedData
   720  	err := json.Unmarshal([]byte(complexTypedDataLCRefType), &td)
   721  	if err != nil {
   722  		t.Fatalf("unmarshalling failed '%v'", err)
   723  	}
   724  	_, sighash, err := sign(td)
   725  	if err != nil {
   726  		t.Fatal(err)
   727  	}
   728  	expSigHash := common.FromHex("0x49191f910874f0148597204d9076af128d4694a7c4b714f1ccff330b87207bff")
   729  	if !bytes.Equal(expSigHash, sighash) {
   730  		t.Fatalf("Error, got %x, wanted %x", sighash, expSigHash)
   731  	}
   732  }