github.com/smartcontractkit/chainlink-testing-framework/libs@v0.0.0-20240227141906-ec710b4eb1a3/docker/test_env/eth2_init_helpers.go (about)

     1  package test_env
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"html/template"
     7  	"os"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/google/uuid"
    12  	"github.com/rs/zerolog"
    13  	"github.com/rs/zerolog/log"
    14  	tc "github.com/testcontainers/testcontainers-go"
    15  
    16  	"github.com/smartcontractkit/chainlink-testing-framework/libs/docker"
    17  	"github.com/smartcontractkit/chainlink-testing-framework/libs/logging"
    18  )
    19  
    20  type AfterGenesisHelper struct {
    21  	EnvComponent
    22  	chainConfig         EthereumChainConfig
    23  	l                   zerolog.Logger
    24  	customConfigDataDir string
    25  	addressesToFund     []string
    26  	t                   *testing.T
    27  }
    28  
    29  func NewInitHelper(chainConfig EthereumChainConfig, customConfigDataDir string, opts ...EnvComponentOption) *AfterGenesisHelper {
    30  	g := &AfterGenesisHelper{
    31  		EnvComponent: EnvComponent{
    32  			ContainerName: fmt.Sprintf("%s-%s", "after-genesis-helper", uuid.NewString()[0:8]),
    33  		},
    34  		chainConfig:         chainConfig,
    35  		customConfigDataDir: customConfigDataDir,
    36  		l:                   log.Logger,
    37  		addressesToFund:     []string{},
    38  	}
    39  	g.SetDefaultHooks()
    40  	for _, opt := range opts {
    41  		opt(&g.EnvComponent)
    42  	}
    43  	return g
    44  }
    45  
    46  func (g *AfterGenesisHelper) WithTestInstance(t *testing.T) *AfterGenesisHelper {
    47  	g.l = logging.GetTestLogger(t)
    48  	g.t = t
    49  	return g
    50  }
    51  
    52  func (g *AfterGenesisHelper) StartContainer() error {
    53  	r, err := g.getContainerRequest(g.Networks)
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	l := logging.GetTestContainersGoTestLogger(g.t)
    59  	_, err = docker.StartContainerWithRetry(g.l, tc.GenericContainerRequest{
    60  		ContainerRequest: *r,
    61  		Reuse:            true,
    62  		Started:          true,
    63  		Logger:           l,
    64  	})
    65  	if err != nil {
    66  		return fmt.Errorf("cannot start after genesis helper container: %w", err)
    67  	}
    68  
    69  	g.l.Info().Str("containerName", g.ContainerName).
    70  		Msg("Started After Genesis Helper container")
    71  
    72  	return nil
    73  }
    74  
    75  func (g *AfterGenesisHelper) getContainerRequest(networks []string) (*tc.ContainerRequest, error) {
    76  	initScriptFile, err := os.CreateTemp("", "init.sh")
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	initScript, err := g.buildInitScript()
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	_, err = initScriptFile.WriteString(initScript)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	return &tc.ContainerRequest{
    92  		Name:          g.ContainerName,
    93  		Image:         "protolambda/eth2-val-tools:latest",
    94  		ImagePlatform: "linux/x86_64",
    95  		Networks:      networks,
    96  		WaitingFor: NewExitCodeStrategy().WithExitCode(0).
    97  			WithPollInterval(1 * time.Second).WithTimeout(10 * time.Second),
    98  		Entrypoint: []string{"sh", "/init.sh"},
    99  		Files: []tc.ContainerFile{
   100  			{
   101  				HostFilePath:      initScriptFile.Name(),
   102  				ContainerFilePath: "/init.sh",
   103  				FileMode:          0744,
   104  			},
   105  		},
   106  		Mounts: tc.ContainerMounts{
   107  			tc.ContainerMount{
   108  				Source: tc.GenericBindMountSource{
   109  					HostPath: g.customConfigDataDir,
   110  				},
   111  				Target: tc.ContainerMountTarget(GENERATED_DATA_DIR_INSIDE_CONTAINER),
   112  			},
   113  		},
   114  		LifecycleHooks: []tc.ContainerLifecycleHooks{
   115  			{
   116  				PostStarts: g.PostStartsHooks,
   117  				PostStops:  g.PostStopsHooks,
   118  			},
   119  		},
   120  	}, nil
   121  }
   122  
   123  func (g *AfterGenesisHelper) buildInitScript() (string, error) {
   124  	initTemplate := `#!/bin/bash
   125  echo "Saving wallet password to {{.WalletPasswordFileLocation}}"
   126  echo "{{.WalletPassword}}" > {{.WalletPasswordFileLocation}}
   127  echo "Saving execution client keystore file to {{.AccountKeystoreFileLocation}}"
   128  mkdir -p {{.KeystoreDirLocation}}
   129  echo '{"address":"123463a4b065722e99115d6c222f267d9cabb524","crypto":{"cipher":"aes-128-ctr","ciphertext":"93b90389b855889b9f91c89fd15b9bd2ae95b06fe8e2314009fc88859fc6fde9","cipherparams":{"iv":"9dc2eff7967505f0e6a40264d1511742"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c07503bb1b66083c37527cd8f06f8c7c1443d4c724767f625743bd47ae6179a4"},"mac":"6d359be5d6c432d5bbb859484009a4bf1bd71b76e89420c380bd0593ce25a817"},"id":"622df904-0bb1-4236-b254-f1b8dfdff1ec","version":3}' > {{.AccountKeystoreFileLocation}}
   130  echo "Saving execution client account password to {{.AccountPasswordFileLocation}}"
   131  echo "" > {{.AccountPasswordFileLocation}}
   132  echo "Saving jwt secret to {{.JwtFileLocation}}"
   133  echo "0xfad2709d0bb03bf0e8ba3c99bea194575d3e98863133d1af638ed056d1d59345" > {{.JwtFileLocation}}
   134  echo "All done!"
   135  echo 
   136  echo "------------------------------------------------------------------"
   137  formatted_genesis_date=$(date -d "@{{.GenesisTimestamp}}" '+%Y-%m-%d %H:%M:%S')
   138  echo "Chain genesis timestamp: $formatted_genesis_date UTC"
   139  
   140  current_timestamp=$(date +%s)
   141  time_diff=$(({{.GenesisTimestamp}} - current_timestamp))
   142  echo "More or less $time_diff seconds from now"
   143  echo "------------------------------------------------------------------"
   144  `
   145  
   146  	data := struct {
   147  		WalletPassword              string
   148  		WalletPasswordFileLocation  string
   149  		AccountPasswordFileLocation string
   150  		JwtFileLocation             string
   151  		AccountKeystoreFileLocation string
   152  		KeystoreDirLocation         string
   153  		GenesisTimestamp            int
   154  	}{
   155  		WalletPassword:              WALLET_PASSWORD,
   156  		WalletPasswordFileLocation:  VALIDATOR_WALLET_PASSWORD_FILE_INSIDE_CONTAINER,
   157  		AccountPasswordFileLocation: ACCOUNT_PASSWORD_FILE_INSIDE_CONTAINER,
   158  		JwtFileLocation:             JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER,
   159  		AccountKeystoreFileLocation: ACCOUNT_KEYSTORE_FILE_INSIDE_CONTAINER,
   160  		KeystoreDirLocation:         KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER,
   161  		GenesisTimestamp:            g.chainConfig.genesisTimestamp,
   162  	}
   163  
   164  	t, err := template.New("init").Parse(initTemplate)
   165  	if err != nil {
   166  		fmt.Println("Error parsing template:", err)
   167  		os.Exit(1)
   168  	}
   169  
   170  	var buf bytes.Buffer
   171  	err = t.Execute(&buf, data)
   172  
   173  	return buf.String(), err
   174  }