하나하나 알아가는 재미

in #sct6 years ago (edited)

안녕하세요 @realmankwon입니다.

KRWP 보상 자동화가 막바지에 이르렀습니다.
조만간 베타테스터를 모집할 것 같습니다.
운영진 테스트로는 하루에 5~6건 정도 처리해 왔고 그 사이 이런저런 문제들이 하나둘 찾아져서 수정을 하고 있습니다.

그런 문제들 대부분은 코딩량은 얼마되지 않습니다.
아주 사소한 부분이지만 파급효과는 엄청납니다.
그런 것들 중에 대표적인 것을 한번 정리해 보고자 합니다.

1 . 스팀 API

1 ) 스팀 블록

  • 대충 알고 있었던 스팀 블록에 대해서 자세하게 알게되는 계기가 되었습니다. 일단 스팀 블록의 대략적인 형태는 다음과 같습니다.

  • 이때 스팀 API는 필요한 정보에 따라 다른 것을 쓰게 됩니다.
    API도 steem, dsteem 등 여러가지가 있습니다.

getBlock : Block 전체를 가지고 옵니다.
getTransaction : Transaction 만 가지고 옵니다.
getOperation : Operation 만 가지고 옵니다.

2 ) irreversible 블록의 존재

  • 스팀 블록을 몽고 DB에 저장하고 이 데이터를 근거로 많은 프로젝트를 진행 중에 있습니다.
    최초에는 위에서 언급한 getBlock 함수로 전체 블록 정보를 가지고 온 다음에 내부에 Transaction 들의 정보를 찾으면서 데이터를 저장했습니다. SCOT의 경우 Transaction 내부에서 operations[0][0]의 값이 custom_json 인 것만 가지고 오면 됩니다.
  • 하지만 KRWP 보상 자동화의 경우 베네피셔리 설정으로 인한 보상이 실제로 얼마인지가 가장 중요합니다. 이 베네피셔리 보상 정보를 steemd.com에서 찾아보니 다음과 같이 virtual로 표시 되고 있었습니다.

  • 저 정보는 getBlock 으로는 가지고 올 수 없는 정보였습니다. 정보를 찾아보니 Block 은 Block header와 Block irreversible로 나뉘어져 있었습니다. 일반적인 Operation 은 Block header영역에 저장이 되고 보상의 결과 저자 보상, 큐레 보상, 베네피셔리 보상 등은 Block irreversible 영역에 저장되었습니다.

  • 그래서 기존의 Transaction 은 getBlock 으로 베네피셔리 보상 정보는 getOperation 으로 가지고 와서 정보를 저장하도록 처리하여 베네피셔리를 설정한 스팀 보상은 정확하게 처리할 수 있었습니다.

3 ) irreversible 블록의 생성 시점

  • getOperation을 사용하여 베네피셔리를 설정한 스팀 보상 정보를 저장하게 했음에도 불구하고 몽고 DB에 저장되지 않은 경우가 많이 발생했습니다. 이전 포스팅에도 언급했듯이 나중에 다시 동일 소스로 동일 블록 정보를 가지고 오면 정보를 정상적으로 가지고 와서 입력하였습니다.

  • 테스트 결과 irreversible 블록은 Block header 가 생성된 이후 30초~60초 정도가 지나야 생성이 되었습니다. 실시간으로 처리하고자 욕심을 부린 것이 오히려 화근이었습니다. 이것을 알고나니 왜 busy와 steempeak에서 우측 상단의 알림 기능이 1~2분씩 늦게 오는지 이해가 되었습니다.

  • 몽고 DB 데이터 저장 로직을 변경을 하였습니다. 현재 시간과 2분 이내의 블럭을 저장하면 0.01초 간격으로 다음 블록을 저장하고 3분의 차이가 생기면 1.5초 간격으로 저장하여 탄력적으로 운영하여 2분~3분의 차이를 유지하도록 설정한 이후에는 아주 잘 저장이 되고 있습니다.

2 . Javascript 공부

1 ) 비동기 언어의 동기 처리

  • Javascript 가 왜 요즘 핫한 언어가 되었나 생각해 보면 바로 비동기 언어인 것이 가장 큰 것 같습니다.
    비동기 언어의 경우 어떤 일을 처리하는 동안 다른 일을 하다가 이전의 일이 완료가 되면 그때 그 일을 마무리 지을 수 있는 특징이 있습니다.

  • 빅데이터의 경우 대용량의 데이터를 처리해야 하는데 하나를 처리하는 동안 다른 것을 처리할 수 있으면 효율이 높아지기 때문에 비동기 언어를 택하게 되었습니다.
    그 중심에 Javascript가 있는 것 같습니다.

  • 스팀 관련 개발을 하면서 비동기 언어임에도 불구하고 순서대로 처리해야 하는 일이 허다합니다. 예를 들어 10 sct 를 전송해야 한다면 현재 가지고 있는 수량을 가지고 와서 10 sct가 되는지 확인한 후에 전송을 해야 합니다. 그때 수량을 가지고 오는 API의 리턴값을 기다려야 하고 그 이후에 값을 확인 한 후 전송을 해야 합니다.

  • 이 부분을 잘 처리해야 하는데 그동안 javascript 가 많이 발전을 해서 그 사이에 변화된 문법을 공부해야 했습니다.

2 ) await, promise

  • 비동기인 함수를 동기 방식으로 변경시켜주는 것이 promise 입니다. 문법적으로는 다음과 같이 작성이 됩니다.

      async sct() {
              return (new Promise (resolve, reject) => {
                     if(success) resolve();
                     else reject();
             });
     }
    
  • promise 함수를 호출하는 곳에서는 다음과 같이 await 를 이용합니다.

     try{
             const result = await sct();
     } catch(e) {
             console.log(e);
     }
    
  • 저렇게 하면 success로 resolve, reject 함수가 호출되기 전까지는 await sct() 다음으로 넘어가지 않습니다. resolve가 호출되면 정상적으로 수행이 되고 reject가 호출되면 catch로 넘어가서 exception e가 출력되게 됩니다. 제가 개발한 봇이 가끔씩 뻗을때가 있었는데 await, promise 의 동작 방식을 완전히 이해하고 보니 그 부분이 보였습니다.
    resolve, reject가 호출이 되지 않게 작성한 경우 실제로 뻗지는 않았지만 중단점이 없기 때문에 다음으로 넘어가지 않았던 것입니다.

  • 봇의 안정화 대부분이 모든 함수의 await, promise 적용, try catch를 통한 예외 처리였습니다. 발생할 수 있는 모든 예외 부분을 찾고 찾고 찾아서 그 부분을 정상적인 루틴으로 돌려 놓는 것입니다.

현재 이렇게 돌고 있는 봇이 제가 작성한 것만 3개의 봇이 있습니다.
어떤 것은 스팀 자체의 특성에 대해서 모르는 것이고 어떤 것은 개발 스킬의 부족에서 기인한 것입니다.
하지만 그것들을 하나하나 알아가는 것만으로도 참 기쁜 일입니다.
스팀을 통해 sct를 통해 얼마나 많은 금전적 이익을 가지게 될지는 모르겠습니다.
지금까지 제가 투자한 모든 암호화폐는 참담할 만큼 실패했습니다.
그런데 이번에는 지식이 남고 소스가 남고 같이 한 사람이 남을 것 같아서 참 좋습니다. ^^

Sort:  

고생하셨습니다. 덕분에 저도 스팀 블록 구조에 대해서 알게되었네요. ㅎㅎ

안피곤님은 원래 잘 아시는걸로 ㅎㅎ

자세한 설명 잘 읽었습니다. 노드 비동기가 참 좋은데, 적응이 안되네요.

비동기 첨에는 정말 적응이 안 되죠... ㅜㅜ
저도 어차피 비동기를 동기로 쓰는거라 잘 쓰고 있는건지 모르겠습니다 ^^

많은 일을 하고 계신데 그 일들이 기쁘다고 하니 이 보다 더 좋은 일이 없을 것 같습니다. 앞으로 더 좋은 일들도 많이 생겨서 투자의 실패가 좋은 경험이 되었다고 회고 하시는 날이 오길 기대합니다.

언젠가 같은 열매를 따 먹는 날이 오길 기다립니다 ^^

항상 고생이 많으십니다. 감사합니다.

감사합니다 ^^

요즘 블록 정보 가져오는거 공부하고 있는데, 도움이 많이 되었습니다~

요즘 제일 핫한 개발자이신 것 같습니다 ^^
개발 포스팅도 매일매일 꾸준히 올라오시구요 ㅎ
알고 계신 내용이었을텐데 읽어주셔서 감사합니다~

공부 시작한지 얼마되지 않아 아직 모르는게 너무 많습니다.

앞으로도 하나씩 하나씩 꾸준히 알아가야죠~