본문 바로가기
Blockchain/Ethereum

[ Geth ] 파헤치기 4 번 - geth 함수 살펴보기

by 기저귀찬개발자 2019. 6. 24.

관련글

2019/04/15 - [Blockchain/Ethereum] - [ Geth ] 파헤치기 1 번 - Geth 실행 및 디버깅 방법

2019/05/06 - [Blockchain/Ethereum] - [ Geth ] 파헤치기 2 번 - 시작 Log 분석하기

2019/06/14 - [Blockchain/Ethereum] - [ Geth ] 파헤치기 3 번 - geth Main 함수 살펴보기

2019/06/24 - [Blockchain/Ethereum] - [ Geth ] 파헤치기 4 번 - geth 함수 살펴보기

 

저번 게시글에서 Main 함수를 알아보았고 app, cli 객체를 선언하고 geth 함수 진입부까지 살펴보았다.

오늘은 geth 함수가 어떤 역할을 하고 어떤 소스가 호출되는지 알아보자

 

설명을 보면 별다른 subcommand가 없으면 실행되는 기본 함수이고, 

geth 실행 옵션을 통해 default node를 생성하는 함수이다.

makeFullNode() 함수가 노드를 구성하는 중요한 함수로 보인다.

 

-> defer 키워드는 지연 함수 키워드로 함수가 끝나고 실행될 명령어를 모아놓는 스택이라 볼 수 있다. 

     호출된 역순으로 실행시킨다.

// geth is the main entry point into the system if no special subcommand is ran.
// It creates a default node based on the command line arguments and runs it in
// blocking mode, waiting for it to be shut down.
func geth(ctx *cli.Context) error {

	if args := ctx.Args(); len(args) > 0 {
		return fmt.Errorf("invalid command: %q", args[0])
	}
	node := makeFullNode(ctx)
	defer node.Close()
	startNode(ctx, node)

	node.Wait()
	return nil
}

 

- makeFullNode() 함수는 /cmd/geth/config.go 에 선언되어 있다.

- 첫줄에서 makeConfigNode 함수 또한 같은 파일에 있으며 아래 소스 구문에 포함했다.

- makeConfigNode 에서는 설정값에 따라 ULC( Ultra Light Client ) 모드, p2p, ipc, http, ws, datadir,shh, dashboard 사용   셋팅 등의  여러 config 설정에 대한 셋팅을 담당한다.

 

 


func makeFullNode(ctx *cli.Context) *node.Node {
	stack, cfg := makeConfigNode(ctx)

	if ctx.GlobalIsSet(utils.ConstantinopleOverrideFlag.Name) {
		cfg.Eth.ConstantinopleOverride = new(big.Int).SetUint64(ctx.GlobalUint64(utils.ConstantinopleOverrideFlag.Name))
	}
	utils.RegisterEthService(stack, &cfg.Eth)

	if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
		utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
	}
	// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
	shhEnabled := enableWhisper(ctx)
	shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
	if shhEnabled || shhAutoEnabled {
		if ctx.GlobalIsSet(utils.WhisperMaxMessageSizeFlag.Name) {
			cfg.Shh.MaxMessageSize = uint32(ctx.Int(utils.WhisperMaxMessageSizeFlag.Name))
		}
		if ctx.GlobalIsSet(utils.WhisperMinPOWFlag.Name) {
			cfg.Shh.MinimumAcceptedPOW = ctx.Float64(utils.WhisperMinPOWFlag.Name)
		}
		if ctx.GlobalIsSet(utils.WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
			cfg.Shh.RestrictConnectionBetweenLightClients = true
		}
		utils.RegisterShhService(stack, &cfg.Shh)
	}

	// Configure GraphQL if required
	if ctx.GlobalIsSet(utils.GraphQLEnabledFlag.Name) {
		if err := graphql.RegisterGraphQLService(stack, cfg.Node.GraphQLEndpoint(), cfg.Node.GraphQLCors, cfg.Node.GraphQLVirtualHosts, cfg.Node.HTTPTimeouts); err != nil {
			utils.Fatalf("Failed to register the Ethereum service: %v", err)
		}
	}

	// Add the Ethereum Stats daemon if requested.
	if cfg.Ethstats.URL != "" {
		utils.RegisterEthStatsService(stack, cfg.Ethstats.URL)
	}
	return stack
}



func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
	// Load defaults.
	cfg := gethConfig{
		Eth:       eth.DefaultConfig,
		Shh:       whisper.DefaultConfig,
		Node:      defaultNodeConfig(),
		Dashboard: dashboard.DefaultConfig,
	}

	// Load config file.
	if file := ctx.GlobalString(configFileFlag.Name); file != "" {
		if err := loadConfig(file, &cfg); err != nil {
			utils.Fatalf("%v", err)
		}
	}

	// Apply flags.
	utils.SetULC(ctx, &cfg.Eth)
	utils.SetNodeConfig(ctx, &cfg.Node)
	stack, err := node.New(&cfg.Node)
	if err != nil {
		utils.Fatalf("Failed to create the protocol stack: %v", err)
	}
	utils.SetEthConfig(ctx, stack, &cfg.Eth)
	if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) {
		cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name)
	}

	utils.SetShhConfig(ctx, stack, &cfg.Shh)
	utils.SetDashboardConfig(ctx, &cfg.Dashboard)

	return stack, cfg
}

 

위 makeFullNode 함수에서 중간에 위치한 utils.RegisterEthService(stack, &cfg.Eth) 함수가 호출된 뒤 실제로 노드를 쌓는 작업을 시작하게 된다. RegisterEthService 함수는 아래와 같다. 

 

// RegisterEthService adds an Ethereum client to the stack.
func RegisterEthService(stack *node.Node, cfg *eth.Config) {
	var err error
	if cfg.SyncMode == downloader.LightSync {
		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
			return les.New(ctx, cfg)
		})
	} else {
		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
			fullNode, err := eth.New(ctx, cfg)
			if fullNode != nil && cfg.LightServ > 0 {
				ls, _ := les.NewLesServer(fullNode, cfg)
				fullNode.AddLesServer(ls)
			}
			return fullNode, err
		})
	}
	if err != nil {
		Fatalf("Failed to register the Ethereum service: %v", err)
	}
}

 

그 중 les 객체(https://github.com/ethereum/go-ethereum/tree/master/les)가 이더리움 Sync 모드에 따라 다른 node를 생성하게 되는데 다음 장에서는 해당 객체에 대해서 더 자세히 

알아보도록 하겠다. 슬슬 내용이 어려워져서 내가 설명을 봐도 두서없고 부족한 부분은 일단 진행 후 이해를 한 뒤에 와서

보충을 해야겠다. ㅜㅜㅜㅜ  

댓글