github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/sfc_test.go (about)

     1  package gossip
     2  
     3  // compile SFC with truffle
     4  //go:generate bash -c "cd ../../u2u-sfc && git checkout 8ff03212140f8440f1dea2c63826528ceff91074"
     5  //go:generate bash -c "docker run --name go-u2u-sfc-compiler -v $(pwd)/contract/solc:/src/build/contracts -v $(pwd)/../../u2u-sfc:/src -w /src node:18-buster bash -c 'export NPM_CONFIG_PREFIX=~; npm install --no-save; npm install --no-save truffle@5.2.4' && docker commit go-u2u-sfc-compiler go-u2u-sfc-compiler-image && docker rm go-u2u-sfc-compiler"
     6  //go:generate bash -c "docker run --rm -v $(pwd)/contract/solc:/src/build/contracts -v $(pwd)/../../u2u-sfc:/src -w /src go-u2u-sfc-compiler-image bash -c 'export NPM_CONFIG_PREFIX=~; rm -f /src/build/contracts/*json; npm run build'"
     7  //go:generate bash -c "cd ./contract/solc && for f in SFC.json SFCLib.json; do jq -j .bytecode $DOLLAR{f} > $DOLLAR{f%.json}.bin; jq -j .deployedBytecode $DOLLAR{f} > $DOLLAR{f%.json}.bin-runtime; jq -c .abi $DOLLAR{f} > $DOLLAR{f%.json}.abi; done"
     8  //go:generate bash -c "docker run --rm -v $(pwd)/contract/solc:/src/build/contracts -v $(pwd)/../../u2u-sfc:/src -w /src go-u2u-sfc-compiler-image bash -c 'export NPM_CONFIG_PREFIX=~; sed -i s/runs:\\ 200,/runs:\\ 10000,/ /src/truffle-config.js; rm -f /src/build/contracts/*json; npm run build'"
     9  //go:generate bash -c "cd ../../u2u-sfc && git checkout -- truffle-config.js; docker rmi go-u2u-sfc-compiler-image"
    10  //go:generate bash -c "cd ./contract/solc && for f in NetworkInitializer.json NodeDriver.json NodeDriverAuth.json; do jq -j .bytecode $DOLLAR{f} > $DOLLAR{f%.json}.bin; jq -j .deployedBytecode $DOLLAR{f} > $DOLLAR{f%.json}.bin-runtime; jq -c .abi $DOLLAR{f} > $DOLLAR{f%.json}.abi; done"
    11  
    12  // wrap SFC with golang
    13  //go:generate mkdir -p ./contract/sfc100
    14  //go:generate go run github.com/unicornultrafoundation/go-u2u/libs/cmd/abigen --bin=./contract/solc/SFC.bin --abi=./contract/solc/SFC.abi --pkg=sfc100 --type=Contract --out=contract/sfc100/contract.go
    15  //go:generate bash -c "(echo -ne '\nvar ContractBinRuntime = \"'; cat contract/solc/SFC.bin-runtime; echo '\"') >> contract/sfc100/contract.go"
    16  // wrap SFC lib with golang
    17  //go:generate mkdir -p ./contract/sfclib100
    18  //go:generate go run github.com/unicornultrafoundation/go-u2u/libs/cmd/abigen --bin=./contract/solc/SFCLib.bin --abi=./contract/solc/SFCLib.abi --pkg=sfclib100 --type=Contract --out=contract/sfclib100/contract.go
    19  //go:generate bash -c "(echo -ne '\nvar ContractBinRuntime = \"'; cat contract/solc/SFCLib.bin-runtime; echo '\"') >> contract/sfclib100/contract.go"
    20  // wrap NetworkInitializer with golang
    21  //go:generate mkdir -p ./contract/netinit100
    22  //go:generate go run github.com/unicornultrafoundation/go-u2u/libs/cmd/abigen --bin=./contract/solc/NetworkInitializer.bin --abi=./contract/solc/NetworkInitializer.abi --pkg=netinit100 --type=Contract --out=contract/netinit100/contract.go
    23  //go:generate bash -c "(echo -ne '\nvar ContractBinRuntime = \"'; cat contract/solc/NetworkInitializer.bin-runtime; echo '\"') >> contract/netinit100/contract.go"
    24  // wrap NodeDriver with golang
    25  //go:generate mkdir -p ./contract/driver100
    26  //go:generate go run github.com/unicornultrafoundation/go-u2u/libs/cmd/abigen --bin=./contract/solc/NodeDriver.bin --abi=./contract/solc/NodeDriver.abi --pkg=driver100 --type=Contract --out=contract/driver100/contract.go
    27  //go:generate bash -c "(echo -ne '\nvar ContractBinRuntime = \"'; cat contract/solc/NodeDriver.bin-runtime; echo '\"') >> contract/driver100/contract.go"
    28  // wrap NodeDriverAuth with golang
    29  //go:generate mkdir -p ./contract/driverauth100
    30  //go:generate go run github.com/unicornultrafoundation/go-u2u/libs/cmd/abigen --bin=./contract/solc/NodeDriverAuth.bin --abi=./contract/solc/NodeDriverAuth.abi --pkg=driverauth100 --type=Contract --out=contract/driverauth100/contract.go
    31  //go:generate bash -c "(echo -ne '\nvar ContractBinRuntime = \"'; cat contract/solc/NodeDriverAuth.bin-runtime; echo '\"') >> contract/driverauth100/contract.go"
    32  
    33  import (
    34  	"fmt"
    35  	"math/big"
    36  	"testing"
    37  
    38  	"github.com/stretchr/testify/require"
    39  
    40  	"github.com/unicornultrafoundation/go-helios/native/idx"
    41  	"github.com/unicornultrafoundation/go-u2u/common/hexutil"
    42  	"github.com/unicornultrafoundation/go-u2u/core/types"
    43  	"github.com/unicornultrafoundation/go-u2u/gossip/contract/driver100"
    44  	"github.com/unicornultrafoundation/go-u2u/gossip/contract/driverauth100"
    45  	"github.com/unicornultrafoundation/go-u2u/gossip/contract/netinit100"
    46  	"github.com/unicornultrafoundation/go-u2u/gossip/contract/sfc100"
    47  	"github.com/unicornultrafoundation/go-u2u/logger"
    48  	"github.com/unicornultrafoundation/go-u2u/u2u/contracts/driver"
    49  	"github.com/unicornultrafoundation/go-u2u/u2u/contracts/driverauth"
    50  	"github.com/unicornultrafoundation/go-u2u/u2u/contracts/evmwriter"
    51  	"github.com/unicornultrafoundation/go-u2u/u2u/contracts/netinit"
    52  	"github.com/unicornultrafoundation/go-u2u/u2u/contracts/sfc"
    53  	"github.com/unicornultrafoundation/go-u2u/utils"
    54  )
    55  
    56  func TestSFC(t *testing.T) {
    57  	logger.SetTestMode(t)
    58  	logger.SetLevel("debug")
    59  
    60  	env := newTestEnv(2, 3)
    61  	defer env.Close()
    62  
    63  	var (
    64  		sfc10 *sfc100.Contract
    65  		err   error
    66  	)
    67  
    68  	authDriver10, err := driverauth100.NewContract(driverauth.ContractAddress, env)
    69  	require.NoError(t, err)
    70  	rootDriver10, err := driver100.NewContract(driver.ContractAddress, env)
    71  	require.NoError(t, err)
    72  
    73  	admin := idx.ValidatorID(1)
    74  	adminAddr := env.Address(admin)
    75  
    76  	_ = true &&
    77  		t.Run("Genesis SFC", func(t *testing.T) {
    78  			require := require.New(t)
    79  
    80  			exp := sfc.GetContractBin()
    81  			got, err := env.CodeAt(nil, sfc.ContractAddress, nil)
    82  			require.NoError(err)
    83  			require.Equal(exp, got, "genesis SFC contract")
    84  			require.Equal(exp, hexutil.MustDecode(sfc100.ContractBinRuntime), "genesis SFC contract version")
    85  		}) &&
    86  		t.Run("Genesis Driver", func(t *testing.T) {
    87  			require := require.New(t)
    88  
    89  			exp := driver.GetContractBin()
    90  			got, err := env.CodeAt(nil, driver.ContractAddress, nil)
    91  			require.NoError(err)
    92  			require.Equal(exp, got, "genesis Driver contract")
    93  			require.Equal(exp, hexutil.MustDecode(driver100.ContractBinRuntime), "genesis Driver contract version")
    94  		}) &&
    95  		t.Run("Genesis DriverAuth", func(t *testing.T) {
    96  			require := require.New(t)
    97  
    98  			exp := driverauth.GetContractBin()
    99  			got, err := env.CodeAt(nil, driverauth.ContractAddress, nil)
   100  			require.NoError(err)
   101  			require.Equal(exp, got, "genesis DriverAuth contract")
   102  			require.Equal(exp, hexutil.MustDecode(driverauth100.ContractBinRuntime), "genesis DriverAuth contract version")
   103  		}) &&
   104  		t.Run("Network initializer", func(t *testing.T) {
   105  			require := require.New(t)
   106  
   107  			exp := netinit.GetContractBin()
   108  			got, err := env.CodeAt(nil, netinit.ContractAddress, nil)
   109  			require.NoError(err)
   110  			require.NotEmpty(exp, "genesis NetworkInitializer contract")
   111  			require.Empty(got, "genesis NetworkInitializer should be destructed")
   112  			require.Equal(exp, hexutil.MustDecode(netinit100.ContractBinRuntime), "genesis NetworkInitializer contract version")
   113  		}) &&
   114  		t.Run("Builtin EvmWriter", func(t *testing.T) {
   115  			require := require.New(t)
   116  
   117  			exp := []byte{0}
   118  			got, err := env.CodeAt(nil, evmwriter.ContractAddress, nil)
   119  			require.NoError(err)
   120  			require.Equal(exp, got, "builtin EvmWriter contract")
   121  		}) &&
   122  		t.Run("Some transfers I", func(t *testing.T) {
   123  			circleTransfers(t, env, 1)
   124  		}) &&
   125  		t.Run("Check owners", func(t *testing.T) {
   126  			require := require.New(t)
   127  
   128  			opts := env.ReadOnly()
   129  			opts.From = adminAddr
   130  
   131  			isOwn, err := authDriver10.IsOwner(opts)
   132  			require.NoError(err)
   133  			require.True(isOwn)
   134  		}) &&
   135  		t.Run("SFC upgrade", func(t *testing.T) {
   136  			require := require.New(t)
   137  
   138  			// create new
   139  			rr, err := env.ApplyTxs(nextEpoch,
   140  				env.Contract(admin, utils.ToU2U(0), sfc100.ContractBin),
   141  			)
   142  			require.NoError(err)
   143  			require.Equal(1, rr.Len())
   144  			require.Equal(types.ReceiptStatusSuccessful, rr[0].Status)
   145  			newImpl := rr[0].ContractAddress
   146  			require.NotEqual(sfc.ContractAddress, newImpl)
   147  			newSfcContractBinRuntime, err := env.CodeAt(nil, newImpl, nil)
   148  			require.NoError(err)
   149  			require.Equal(hexutil.MustDecode(sfc100.ContractBinRuntime), newSfcContractBinRuntime)
   150  
   151  			tx, err := authDriver10.CopyCode(env.Pay(admin), sfc.ContractAddress, newImpl)
   152  			require.NoError(err)
   153  			rr, err = env.ApplyTxs(sameEpoch, tx)
   154  			require.NoError(err)
   155  			require.Equal(1, rr.Len())
   156  			require.Equal(types.ReceiptStatusSuccessful, rr[0].Status)
   157  			got, err := env.CodeAt(nil, sfc.ContractAddress, nil)
   158  			require.NoError(err)
   159  			require.Equal(newSfcContractBinRuntime, got, "new SFC contract")
   160  
   161  			sfc10, err = sfc100.NewContract(sfc.ContractAddress, env)
   162  			require.NoError(err)
   163  			sfcEpoch, err := sfc10.ContractCaller.CurrentEpoch(env.ReadOnly())
   164  			require.NoError(err)
   165  			require.Equal(0, sfcEpoch.Cmp(big.NewInt(3)), "current SFC epoch %s", sfcEpoch.String())
   166  		})
   167  
   168  	t.Run("Direct driver", func(t *testing.T) {
   169  		require := require.New(t)
   170  
   171  		// create new
   172  		anyContractBin := driver100.ContractBin
   173  		rr, err := env.ApplyTxs(nextEpoch,
   174  			env.Contract(admin, utils.ToU2U(0), anyContractBin),
   175  		)
   176  		require.NoError(err)
   177  		require.Equal(1, rr.Len())
   178  		require.Equal(types.ReceiptStatusSuccessful, rr[0].Status)
   179  		newImpl := rr[0].ContractAddress
   180  
   181  		tx, err := rootDriver10.CopyCode(env.Pay(admin), sfc.ContractAddress, newImpl)
   182  		require.NoError(err)
   183  		rr, err = env.ApplyTxs(sameEpoch, tx)
   184  		require.NoError(err)
   185  		require.Equal(1, rr.Len())
   186  		require.NotEqual(types.ReceiptStatusSuccessful, rr[0].Status)
   187  	})
   188  
   189  }
   190  
   191  func circleTransfers(t *testing.T, env *testEnv, count uint64) {
   192  	require := require.New(t)
   193  	validatorsNum := env.store.GetValidators().Len()
   194  
   195  	// save start balances
   196  	balances := make([]*big.Int, validatorsNum)
   197  	for i := range balances {
   198  		balances[i] = env.State().GetBalance(env.Address(idx.ValidatorID(i + 1)))
   199  	}
   200  
   201  	for i := uint64(0); i < count; i++ {
   202  		// transfers
   203  		txs := make([]*types.Transaction, validatorsNum)
   204  		for i := idx.Validator(0); i < validatorsNum; i++ {
   205  			from := (i) % validatorsNum
   206  			to := (i + 1) % validatorsNum
   207  			txs[i] = env.Transfer(idx.ValidatorID(from+1), idx.ValidatorID(to+1), utils.ToU2U(100))
   208  		}
   209  
   210  		rr, err := env.ApplyTxs(sameEpoch, txs...)
   211  		require.NoError(err)
   212  		for i, r := range rr {
   213  			fee := big.NewInt(0).Mul(new(big.Int).SetUint64(r.GasUsed), txs[i].GasPrice())
   214  			balances[i] = big.NewInt(0).Sub(balances[i], fee)
   215  		}
   216  	}
   217  
   218  	// check balances
   219  	for i := range balances {
   220  		require.Equal(
   221  			balances[i],
   222  			env.State().GetBalance(env.Address(idx.ValidatorID(i+1))),
   223  			fmt.Sprintf("account%d", i),
   224  		)
   225  	}
   226  }