2022-09-29 20:46:59 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/hex"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"golang.org/x/crypto/sha3"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
|
|
gocrypto "github.com/filecoin-project/go-crypto"
|
|
|
|
"github.com/filecoin-project/go-state-types/builtin/v8/evm"
|
|
|
|
init8 "github.com/filecoin-project/go-state-types/builtin/v8/init"
|
|
|
|
crypto1 "github.com/filecoin-project/go-state-types/crypto"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/lotus/chain/actors"
|
|
|
|
"github.com/filecoin-project/lotus/lib/sigs"
|
|
|
|
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TxTestcase struct {
|
|
|
|
TxJSON string
|
|
|
|
NosigTx string
|
|
|
|
Input EthBytes
|
|
|
|
Output EthTxArgs
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTxArgs(t *testing.T) {
|
|
|
|
testcases, err := prepareTxTestcases()
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.NotEmpty(t, testcases)
|
|
|
|
|
|
|
|
for i, tc := range testcases {
|
|
|
|
comment := fmt.Sprintf("case %d: \n%s\n%s", i, tc.TxJSON, hex.EncodeToString(tc.Input))
|
|
|
|
|
|
|
|
// parse txargs
|
|
|
|
txArgs, err := ParseEthTxArgs(tc.Input)
|
|
|
|
require.Nil(t, err, comment)
|
|
|
|
|
|
|
|
msgRecovered, err := txArgs.OriginalRlpMsg()
|
|
|
|
require.Nil(t, err, comment)
|
|
|
|
require.Equal(t, tc.NosigTx, "0x"+hex.EncodeToString(msgRecovered), comment)
|
|
|
|
|
|
|
|
// verify signatures
|
|
|
|
from, err := txArgs.Sender()
|
|
|
|
require.Nil(t, err, comment)
|
|
|
|
|
|
|
|
smsg, err := txArgs.ToSignedMessage()
|
|
|
|
require.Nil(t, err, comment)
|
|
|
|
|
|
|
|
err = sigs.Verify(&smsg.Signature, from, msgRecovered)
|
|
|
|
require.Nil(t, err, comment)
|
|
|
|
|
|
|
|
// verify data
|
|
|
|
require.Equal(t, tc.Output.ChainID, txArgs.ChainID)
|
|
|
|
require.Equal(t, tc.Output.Nonce, txArgs.Nonce)
|
|
|
|
require.Equal(t, tc.Output.To, txArgs.To)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTransformParams(t *testing.T) {
|
|
|
|
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
|
2022-10-05 16:44:47 +00:00
|
|
|
Bytecode: mustDecodeHex("0x1122334455"),
|
2022-09-29 20:46:59 +00:00
|
|
|
})
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
evmActorCid, ok := actors.GetActorCodeID(actors.Version8, "reward")
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
params, err := actors.SerializeParams(&init8.ExecParams{
|
|
|
|
CodeCID: evmActorCid,
|
|
|
|
ConstructorParams: constructorParams,
|
|
|
|
})
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
var exec init8.ExecParams
|
|
|
|
reader := bytes.NewReader(params)
|
|
|
|
err1 := exec.UnmarshalCBOR(reader)
|
|
|
|
require.Nil(t, err1)
|
|
|
|
|
|
|
|
var evmParams evm.ConstructorParams
|
|
|
|
reader1 := bytes.NewReader(exec.ConstructorParams)
|
|
|
|
err1 = evmParams.UnmarshalCBOR(reader1)
|
|
|
|
require.Nil(t, err1)
|
|
|
|
|
|
|
|
require.Equal(t, mustDecodeHex("0x1122334455"), evmParams.Bytecode)
|
|
|
|
}
|
|
|
|
func TestEcRecover(t *testing.T) {
|
|
|
|
rHex := "0x479ff7fa64cf8bf641eb81635d1e8a698530d2f219951d234539e6d074819529"
|
|
|
|
sHex := "0x4b6146d27be50cdbb2853ba9a42f207af8d730272f1ebe9c9a78aeef1d6aa924"
|
|
|
|
fromHex := "0x3947D223fc5415f43ea099866AB62B1d4D33814D"
|
|
|
|
v := byte(0)
|
|
|
|
|
|
|
|
msgHex := "0x02f1030185012a05f2008504a817c800825208942b87d1cb599bc2a606db9a0169fcec96af04ad3a880de0b6b3a764000080c0"
|
|
|
|
pubKeyHex := "0x048362749392a0e192eff600d21155236c5a0648d300a8e0e44d8617712c7c96384c75825dc5c7595df2a5005fd8a0f7c809119fb9ab36403ed712244fc329348e"
|
|
|
|
|
|
|
|
msg := mustDecodeHex(msgHex)
|
|
|
|
pubKey := mustDecodeHex(pubKeyHex)
|
|
|
|
r := mustDecodeHex(rHex)
|
|
|
|
s := mustDecodeHex(sHex)
|
|
|
|
from := mustDecodeHex(fromHex)
|
|
|
|
|
|
|
|
sig := append(r, s...)
|
|
|
|
sig = append(sig, v)
|
|
|
|
require.Equal(t, 65, len(sig))
|
|
|
|
|
|
|
|
sha := sha3.NewLegacyKeccak256()
|
|
|
|
sha.Write(msg)
|
|
|
|
h := sha.Sum(nil)
|
|
|
|
|
|
|
|
pubk, err := gocrypto.EcRecover(h, sig)
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.Equal(t, pubKey, pubk)
|
|
|
|
|
|
|
|
sha.Reset()
|
|
|
|
sha.Write(pubk[1:])
|
|
|
|
h = sha.Sum(nil)
|
|
|
|
h = h[len(h)-20:]
|
|
|
|
|
|
|
|
require.Equal(t, from, h)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDelegatedSigner(t *testing.T) {
|
|
|
|
rHex := "0xcf1fa52fae9154ba21d67aeca9b42adfe186eb9e426c441051a8473efd190848"
|
|
|
|
sHex := "0x0e6c8c79ffaf35fb8f136c8cf6c5656f1f3befad21f2644321aa6dba58d68737"
|
|
|
|
v := byte(0)
|
|
|
|
|
|
|
|
msgHex := "0x02f08401df5e76038502540be400843b9aca008398968094ff000000000000000000000000000000000003f2832dc6c080c0"
|
|
|
|
pubKeyHex := "0x04cfecc0520d906cbfea387759246e89d85e2998843e56ad1c41de247ce10b3e4c453aa73c8de13c178d94461b6fa3f8b6f74406ce43d2fbab6992d0b283394242"
|
|
|
|
|
|
|
|
msg := mustDecodeHex(msgHex)
|
|
|
|
pubKey := mustDecodeHex(pubKeyHex)
|
|
|
|
r := mustDecodeHex(rHex)
|
|
|
|
s := mustDecodeHex(sHex)
|
|
|
|
from, err := address.NewSecp256k1Address(pubKey)
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
sig := append(r, s...)
|
|
|
|
sig = append(sig, v)
|
|
|
|
require.Equal(t, 65, len(sig))
|
|
|
|
|
|
|
|
signature := &crypto1.Signature{
|
|
|
|
Type: crypto1.SigTypeDelegated,
|
|
|
|
Data: sig,
|
|
|
|
}
|
|
|
|
|
|
|
|
err = sigs.Verify(signature, from, msg)
|
|
|
|
require.Nil(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func prepareTxTestcases() ([]TxTestcase, error) {
|
|
|
|
tcstr := `[{"input":"0x02f84e82013a80808080808080c080a002d9af9415b94bac9fb29efa168e800fe8390ec22dd6dd3b6848632f999e5fa6a04b0bd833d6993eb37c3b0b5f89551cbbd5412b3a1fed84ca1e94ab2b936be12b","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"0\",\"maxPriorityFeePerGas\":\"0\",\"data\":null,\"nonce\":0,\"type\":2,\"chainId\":314}","nosigTx":"0x02cb82013a80808080808080c0"},{"input":"0x02f84f82013a81c8808080808080c080a0a9177c9fc995b0f83480113a62b797a3520e6bc15d0e9c722c662c40d443b893a01eec355e019308be6acf89a55288a40ae247b6f57c0ca31545efea5954f788d5","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"0\",\"maxPriorityFeePerGas\":\"0\",\"data\":null,\"nonce\":200,\"type\":2,\"chainId\":314}","nosigTx":"0x02cc82013a81c8808080808080c0"},{"input":"0x02f84e82013a80808080808080c080a002d9af9415b94bac9fb29efa168e800fe8390ec22dd6dd3b6848632f999e5fa6a04b0bd833d6993eb37c3b0b5f89551cbbd5412b3a1fed84ca1e94ab2b936be12b","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"0\",\"maxPriorityFeePerGas\":\"0\",\"data\":\"\",\"nonce\":0,\"type\":2,\"chainId\":314}","nosigTx":"0x02cb82013a80808080808080c0"},{"input":"0x02f84f82013a81c8808080808080c080a0a9177c9fc995b0f83480113a62b797a3520e6bc15d0e9c722c662c40d443b893a01eec355e019308be6acf89a55288a40ae247b6f57c0ca31545efea5954f788d5","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"0\",\"maxPriorityFeePerGas\":\"0\",\"data\":\"\",\"nonce\":200,\"type\":2,\"chainId\":314}","nosigTx":"0x02cc82013a81c8808080808080c0"},{"input":"0x02f87282013a808080808080a4f8b2cb4f000000000000000000000000ff00000000000000000000000000000000000064c001a0a0ab14f6fcca6c9905f447e961f128f2c00f5a00e7b1ae18f5d4f9e024a9b7a6a06c4126378d89035f4ab6085fa9a01d92bf798cd799b9338f7818bc48bcba0c8e","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"0\",\"maxPriorityFeePerGas\":\"0\",\"data\":\"0xf8b2cb4f000000000000000000000000ff00000000000000000000000000000000000064\",\"nonce\":0,\"type\":2,\"chainId\":314}","nosigTx":"0x02ef82013a808080808080a4f8b2cb4f000000000000000000000000ff00000000000000000000000000000000000064c0"},{"input":"0x02f87382013a81c88080808080a4f8b2cb4f000000000000000000000000ff00000000000000000000000000000000000064c080a0884e063f65a2986844a9e92f9e02561789c231136976715d5afb581435359e87a044295113d06dd7b8bdf105dd412c76fbd966ef6dbe1d8ace984886296a36018c","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"0\",\"maxPriorityFeePerGas\":\"0\",\"data\":\"0xf8b2cb4f000000000000000000000000ff00000000000000000000000000000000000064\",\"nonce\":200,\"type\":2,\"chainId\":314}","nosigTx":"0x02f082013a81c88080808080a4f8b2cb4f000000000000000000000000ff00000000000000000000000000000000000064c0"},{"input":"0x02f85082013a808082ea6080808080c080a02b86cbd16667f7e035bd908d250d842e7d06f888716131de27897655dce01666a055f43bf2a758e6c250a14a31d33056fcb764e0fce4fffdeb0e11d84caa5ca57b","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"60000\",\"maxPriorityFeePerGas\":\"0\",\"data\":null,\"nonce\":0,\"type\":2,\"chainId\":314}","nosigTx":"0x02cd82013a808082ea6080808080c0"},{"input":"0x02f85182013a81c88082ea6080808080c001a07f1e363b3d38607f8854013e68a80750befd3ba78cc9ce116d6ef6a09359a7aea05ef2c89ffc70ef7f2eaae90a2b4b2a4ffb418108d458e1237b26469e6381fdce","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"60000\",\"maxPriorityFeePerGas\":\"0\",\"data\":null,\"nonce\":200,\"type\":2,\"chainId\":314}","nosigTx":"0x02ce82013a81c88082ea6080808080c0"},{"input":"0x02f85082013a808082ea6080808080c080a02b86cbd16667f7e035bd908d250d842e7d06f888716131de27897655dce01666a055f43bf2a758e6c250a14a31d33056fcb764e0fce4fffdeb0e11d84caa5ca57b","output":"{\"to\":null,\"value\":\"0\",\"gasLimit\":0,\"maxFeePerGas\":\"60000\",\"maxPriorityFeePerGas\":\"0\",\"data\":\"\",\"nonce\":0,\"type\":2,\"chainId\":314}","nosigTx":"0x02cd82013a808082ea6080808080c0"},{"input":"0x02f85182013a81c88082ea6080808080c001a07f1e363b3d38607f8854013e68a80750befd3ba78cc9ce116d6ef6a09359a7aea05ef2c89ffc70ef7f2eaae90a2b4b2a4ffb418108d4
|
|
|
|
|
|
|
|
testcases := []struct {
|
|
|
|
Input EthBytes `json:"input"`
|
|
|
|
Output string `json:"output"`
|
|
|
|
NosigTx string `json:"nosigTx"`
|
|
|
|
}{}
|
|
|
|
|
|
|
|
err := json.Unmarshal([]byte(tcstr), &testcases)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
res := []TxTestcase{}
|
|
|
|
for _, tc := range testcases {
|
|
|
|
tx := EthTxArgs{}
|
|
|
|
err := json.Unmarshal([]byte(tc.Output), &tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
res = append(res, TxTestcase{
|
|
|
|
Input: tc.Input,
|
|
|
|
Output: tx,
|
|
|
|
TxJSON: tc.Output,
|
|
|
|
NosigTx: tc.NosigTx,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return res, err
|
|
|
|
}
|