[연재] 이더스캔(etherscan.io)을 만들어 보자 - web3.js로 블럭 정보 저장 2

[연재] 이더스캔(etherscan.io)을 만들어 보자 - web3.js로 블럭 정보 저장 2


앞에서는 현재까지 만들어져 있는 블럭을 제네시스 블럭부터 루핑 돌면서 데이터베이스에 저장하는 것에 대해 알아보았다.
이번 연재에서는 "이 이후로 생기는 블럭에 대해서는 어떻게 저장할 것이냐"에 대한 것이다.
물론 앞에서도 말했지만, 특정 시간 단위로 setInterval을 돌릴 수도 있다.
하지만 실재 저장되는 것하고는 시간 차가 난다.

이를 위해서는 현재 생성되는 블럭의 생성 이벤트를 모니터링할 수 있는 무엇인가가 필요하다.

web3.js의 filter 객체

web3.js에는 블럭이 생성될 때 이를 모니터링할 수 있는 객체가 있는데 이를 filter라고 한다.
현재 마이닝중인 블럭을 모니터링 할 때는 'pending' 옵션을, 새로 생성된 블럭을 모니터링 할 때는 'latest' 를 준다.
다음은 web3.js 문서에 나와 있는 filter에 대한 예제이다.

// can be 'latest' or 'pending'
var filter = web3.eth.filter(filterString);
// OR object are log filter options
var filter = web3.eth.filter(options);

// watch for changes
filter.watch(function(error, result){
  if (!error)
    console.log(result);
});

// Additionally you can start watching right away, by passing a callback:
web3.eth.filter(options, function(error, result){
  if (!error)
    console.log(result);
});

출처: https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethfilter


filter.watch()

위 코드를 보면 알겠지만, 필터를 생성한 다음 watch 함수를 호출하여 이벤트를 모니터링한다.
watch 함수는 새로운 블럭이 생성될 때마다 호출된다.
따라서 이 함수를 사용하면 블럭이 생길 때 마다 블럭 정보를 데이터베이스에  저장할 수 있다.
watch함수에서 리턴되는 resul에는 블럭 해쉬 값이 들어가 있다. 아래 코드는 result를 block_hash로 바꿔 코드를 읽기 쉽게 리펙토링했다.

var filter = web3.eth.filter('latest');
filter.watch(function(error, block_hash) {
web3.eth.getBlock(block_hash, false, function(err, block) {
# TODO: DB에 insert하는 코드
console.log(block);
});
});

web3.eth.getBlock은 스펙을 보면 알겠지만 블럭 번호를 넘겨도 되고, 블럭 해쉬값을 넘겨도 블럭 정보를 읽을 수 있다.

결론

전체 코드는 두 부분으로 구성된다.
현재 블럭 번호를 읽어와서 지금까지 저장된 블럭을 DB에 저장하는 코드(연재 1)와 현 시점에서 계속 쌓이고 있는 블럭을 DB에 저장하는 코드(연재2)이다.

두 코드를 아래와 같이 각각 비동기로 실행하면 된다.

// - 연재 2 코드
saveFromNow();
// - 연재 1 코드
saveUnsyncedBlock();

이렇게 하면 블럭체인에 있는 블럭 정보를 Database에 손쉽게 동기화할 수 있다.