github.com/klaytn/klaytn@v1.12.1/blockchain/system/kip113_test.go (about)

     1  package system
     2  
     3  import (
     4  	"crypto/rand"
     5  	"math/big"
     6  	"testing"
     7  
     8  	"github.com/klaytn/klaytn/accounts/abi/bind"
     9  	"github.com/klaytn/klaytn/accounts/abi/bind/backends"
    10  	"github.com/klaytn/klaytn/blockchain"
    11  	"github.com/klaytn/klaytn/common"
    12  	contracts "github.com/klaytn/klaytn/contracts/system_contracts"
    13  	"github.com/klaytn/klaytn/crypto"
    14  	"github.com/klaytn/klaytn/crypto/bls"
    15  	"github.com/klaytn/klaytn/log"
    16  	"github.com/klaytn/klaytn/params"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func TestReadKip113(t *testing.T) {
    21  	log.EnableLogForTest(log.LvlCrit, log.LvlWarn)
    22  	var (
    23  		senderKey, _ = crypto.GenerateKey()
    24  		sender       = bind.NewKeyedTransactor(senderKey)
    25  
    26  		alloc = blockchain.GenesisAlloc{
    27  			sender.From: {
    28  				Balance: big.NewInt(params.KLAY),
    29  			},
    30  		}
    31  		backend = backends.NewSimulatedBackend(alloc)
    32  
    33  		nodeId        = common.HexToAddress("0xaaaa")
    34  		_, pub1, pop1 = makeBlsKey()
    35  		_, pub2, _    = makeBlsKey()
    36  	)
    37  
    38  	// Deploy Proxy contract
    39  	transactor, contractAddr := deployKip113Mock(t, sender, backend)
    40  
    41  	// With a valid record
    42  	transactor.Register(sender, nodeId, pub1, pop1)
    43  	backend.Commit()
    44  
    45  	caller, _ := contracts.NewKIP113Caller(contractAddr, backend)
    46  
    47  	opts := &bind.CallOpts{BlockNumber: nil}
    48  	owner, _ := caller.Owner(opts)
    49  	assert.Equal(t, sender.From, owner)
    50  	t.Logf("owner: %x", owner)
    51  
    52  	infos, err := ReadKip113All(backend, contractAddr, nil)
    53  	assert.Nil(t, err)
    54  	assert.Equal(t, 1, len(infos))
    55  	assert.Equal(t, pub1, infos[nodeId].PublicKey)
    56  	assert.Equal(t, pop1, infos[nodeId].Pop)
    57  	assert.Nil(t, infos[nodeId].VerifyErr) // valid PublicKeyInfo
    58  
    59  	// With an invalid record
    60  	// Another register() call for the same nodeId overwrites the existing info.
    61  	transactor.Register(sender, nodeId, pub2, pop1) // pub vs. pop mismatch
    62  	backend.Commit()
    63  
    64  	// Returns one record with VerifyErr.
    65  	infos, err = ReadKip113All(backend, contractAddr, nil)
    66  	assert.Nil(t, err)
    67  	assert.Equal(t, 1, len(infos))
    68  	assert.ErrorIs(t, infos[nodeId].VerifyErr, ErrKip113BadPop) // invalid PublicKeyInfo
    69  }
    70  
    71  func TestAllocKip113(t *testing.T) {
    72  	log.EnableLogForTest(log.LvlCrit, log.LvlWarn)
    73  
    74  	var (
    75  		senderKey, _ = crypto.GenerateKey()
    76  		sender       = bind.NewKeyedTransactor(senderKey)
    77  
    78  		nodeId1       = common.HexToAddress("0xaaaa")
    79  		nodeId2       = common.HexToAddress("0xbbbb")
    80  		_, pub1, pop1 = makeBlsKey()
    81  		_, pub2, pop2 = makeBlsKey()
    82  
    83  		abi, _   = contracts.KIP113MockMetaData.GetAbi()
    84  		input, _ = abi.Pack("initialize")
    85  
    86  		alloc = blockchain.GenesisAlloc{
    87  			sender.From: {
    88  				Balance: big.NewInt(params.KLAY),
    89  			},
    90  		}
    91  		backend = backends.NewSimulatedBackend(alloc)
    92  	)
    93  	kip113Addr, _, _, _ := contracts.DeployKIP113Mock(sender, backend)
    94  	backend.Commit()
    95  	contractAddr, _, _, _ := contracts.DeployERC1967Proxy(sender, backend, kip113Addr, input)
    96  	backend.Commit()
    97  	var (
    98  		allocProxyStorage  = AllocProxy(kip113Addr)
    99  		allocKip113Storage = AllocKip113Proxy(AllocKip113Init{
   100  			Infos: BlsPublicKeyInfos{
   101  				nodeId1: {PublicKey: pub1, Pop: pop1},
   102  				nodeId2: {PublicKey: pub2, Pop: pop2},
   103  			},
   104  			Owner: sender.From,
   105  		})
   106  		allocLogicStorage = AllocKip113Logic()
   107  	)
   108  
   109  	// 1. Merge two storage maps
   110  	allocStorage := MergeStorage(allocProxyStorage, allocKip113Storage)
   111  
   112  	// 2. Create storage by calling register()
   113  	contract, _ := contracts.NewKIP113MockTransactor(contractAddr, backend)
   114  
   115  	contract.Register(sender, nodeId1, pub1, pop1)
   116  	contract.Register(sender, nodeId2, pub2, pop2)
   117  	backend.Commit()
   118  
   119  	// 3. Compare the two states
   120  	compareStorage(t, backend, contractAddr, allocStorage)
   121  	compareStorage(t, backend, kip113Addr, allocLogicStorage)
   122  }
   123  
   124  func deployKip113Mock(t *testing.T, sender *bind.TransactOpts, backend *backends.SimulatedBackend, params ...interface{}) (*contracts.KIP113MockTransactor, common.Address) {
   125  	// Prepare input data for ERC1967Proxy constructor
   126  	abi, err := contracts.KIP113MockMetaData.GetAbi()
   127  	assert.Nil(t, err)
   128  	data, err := abi.Pack("initialize")
   129  	assert.Nil(t, err)
   130  
   131  	// Deploy Proxy contract
   132  	// 1. Deploy KIP113Mock implementation contract
   133  	implAddr, _, _, err := contracts.DeployKIP113Mock(sender, backend)
   134  	backend.Commit()
   135  	assert.Nil(t, err)
   136  	t.Logf("KIP113Mock impl at %x", implAddr)
   137  
   138  	// 2. Deploy ERC1967Proxy(KIP113Mock.address, _data)
   139  	contractAddr, _, _, err := contracts.DeployERC1967Proxy(sender, backend, implAddr, data)
   140  	backend.Commit()
   141  	assert.Nil(t, err)
   142  	t.Logf("ERC1967Proxy at %x", contractAddr)
   143  
   144  	// 3. Attach KIP113Mock contract to the proxy
   145  	transactor, _ := contracts.NewKIP113MockTransactor(contractAddr, backend)
   146  
   147  	return transactor, contractAddr
   148  }
   149  
   150  func compareStorage(t *testing.T, backend *backends.SimulatedBackend, contractAddr common.Address, allocStorage map[common.Hash]common.Hash) {
   151  	execStorage := make(map[common.Hash]common.Hash)
   152  	stateDB, _ := backend.BlockChain().State()
   153  	stateDB.ForEachStorage(contractAddr, func(key common.Hash, value common.Hash) bool {
   154  		execStorage[key] = value
   155  		return true
   156  	})
   157  
   158  	for k, v := range allocStorage {
   159  		assert.Equal(t, v.Hex(), execStorage[k].Hex(), k.Hex())
   160  		t.Logf("%x %x\n", k, v)
   161  	}
   162  	for k, v := range execStorage {
   163  		assert.Equal(t, v.Hex(), allocStorage[k].Hex(), k.Hex())
   164  	}
   165  }
   166  
   167  func makeBlsKey() (priv, pub, pop []byte) {
   168  	ikm := make([]byte, 32)
   169  	rand.Read(ikm)
   170  
   171  	sk, _ := bls.GenerateKey(ikm)
   172  	pk := sk.PublicKey()
   173  	sig := bls.PopProve(sk)
   174  
   175  	priv = sk.Marshal()
   176  	pub = pk.Marshal()
   177  	pop = sig.Marshal()
   178  	if len(priv) != 32 || len(pub) != 48 || len(pop) != 96 {
   179  		panic("bad bls key")
   180  	}
   181  	return
   182  }