brunch

You can make anything
by writing

- C.S.Lewis -

by rudnine Mar 18. 2017

Inside an Ethereum transaction

공부하기 위해서 번역하는 글입니다.

원문 : https://medium.com/@codetractio/inside-an-ethereum-transaction-fa94ffca912f




이더리움은 거래를 기반으로 하는 상태 머신이라 생각 할 수 있습니다.

거래(transactions)는 상태(state)를 바꿀 수 있고, 상태는 상호작용을 추적합니다.

여기서 우리는 거래의 구성요소를 상위수준에서 조사하고, 대부분의 이해할 수 없는 hex값이 어떻게 결정되는지 설명합니다.


이 튜토리얼에서는 nodejs를 사용할 것입니다. 따라서 tx.js 파일을 만들고, 의존성을 요구하는 것으로 시작합니다.


var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
var util = require('ethereumjs-util');
var tx = require('ethereumjs-tx');


첫번째로 개인키와 함께 시작합니다. *private key

이더리움은 공개키 암호방식을 사용합니다. *public key cryptography

보다 구체적으로 말해서, 타원 곡선 전자 서명 알고리즘(secp256k1을 활용한 ECDSA)이 사용되었습니다.

*Elliptic Curve Digital Signature Algorithm

개인 키는 일부 제약사항을 제외하고, 임의의 256비트 데이터입니다.

예를 들면..


var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';


이에 대응하는 공개 키를 도출 하려면


var publicKey = util.bufferToHex(util.privateToPublic(privateKey));


공개 키를 출력하면 다음과 같은 결과를 얻게 됩니다.


0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27


이 개인 키와 관련된 Ethereum 주소는 공개 키의 SHA3-256 (Keccak) 해시의 마지막 160 비트입니다.


var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);
//0x53ae893e4b22d707943299a8d0c844df0e3d5557





보시다시피, 여러개의 개인 키가 동일한 주소를 가질 수 있습니다. Ethereum 계정은 각 주소마다 연결되어 있으며 각 주소는 다음과 같습니다.


nonce : 0으로 시작하는 외부 트랙잭션의 갯수

balance : 계정에 있는 이더의 양

storageRoot : 계정의 스토리지와 관련된 해시

codeHash : 계정을 관리하는 코드의 해시. 비어 있으면 계정은 비공개 키를 사용하여 액세스 할 수있는 일반 계정입니다. 그렇지 않으면 상호 작용에 코드가 적용되는 스마트 계약입니다.


다음으로 거래(transaction)를 살펴보면 6 개의 입력 필드가 있습니다.


nonce : 0으로 시작하는 외부 트랙잭션의 갯수

gasPrice : 거래가 발생하는 이더의 양을 결정하는 가격

gasLimit : 거래를 처리하는 데 허용되는 최대 가스

to : 트랜잭션이 전송되는 계정. 비어 있으면 트랜잭션이 계약을 생성

value : 보낼 이더의 양

data : 임의의 메세지 or 계약에 대한 함수 호출 or 계약을 생성하는 코드


1000 wei의 ether를 보내고 0xc0de 메시지를 남기는 트랜잭션은 다음과 같이 구성 될 수 있습니다.



var rawTx = {
    nonce: web3.toHex(0),
    gasPrice: web3.toHex(20000000000),
    gasLimit: web3.toHex(100000),
    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
    value: web3.toHex(1000),
    data: '0xc0de'
};



보낸 사람 주소가 지정되지 않았으므로,

개인 키로 사인한 후에 서명으로부터 파생됩니다.

거래에 사인하려면..



var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');
var transaction = new tx(rawTx);
transaction.sign(p);




그런 다음 트랜잭션을 네트워크로 보내고 256 비트 트랜잭션 ID로 추적합니다. 이 트랜잭션은 Etherscan에서 볼 수 있습니다. 트랜잭션 ID는 트랜잭션의 해시입니다.


console.log(util.bufferToHex(transaction.hash(true)));
//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662



다음으로, 함수 호출을 위해 무엇이 'data'를 구성하는지 살펴볼 것입니다.

예를 들어, 계약에 대한 이 거래의 데이터는..


console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff


어떤 기능이 호출되는지 알기 위해서는 계약의 기능을 미리 알고 해시 테이블을 작성해야합니다.

첫 번째 32 비트 'a9059cbb'는 해시함수의 첫 번째 32 비트입니다.

이 경우 함수는 다음과 같습니다.

transfer(address _to, uint256 _value)

그리고 그 해시는...


console.log(web3.sha3('transfer(address,uint256)'));
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b


각 인수에 256 비트가옵니다.이 경우 주소는 다음과 같습니다.


0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e


그리고, unsigned integer는 다음과 같습니다.


0x000000000000000000000000000000000000000000000000d02ab486cedbffff




다음으로 위에서 설명한대로 'to'필드를 생략하면 계약이 생성됩니다.

그렇다면, 계약의 주소는 어떻게 결정될까요?

예를 들어, 이 거래는...


console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);
//0x950041c1599529a9f64cf2be59ffb86072f00111


계약 주소는 발신자 주소의 마지막 160비트 해시이며, nonce는 미리 결정될 수 있습니다. 이 거래를 위해 발신자와 nonce는 다음과 같이 확인할 수 있습니다.


var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');
console.log(contractTx.from);
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f
console.log(contractTx.nonce);
//0


따라서 계약주소는 다음과 같습니다.


console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));
//0x950041c1599529a9f64cf2be59ffb86072f00111




이제 우리는이 16 진수에 대해 조금 더 알게되었습니다!


Ethereum과 smart contracts는 많은 산업을 혼란에 빠뜨릴 큰 잠재력을 가지고 있습니다. 온라인 자료가 많이 있으며, 아래에서 Ethereum 탐구 여행을 계속할 수 있습니다!


Ethereum main site https://www.ethereum.org/
Mist, one of Ethereum’s client https://github.com/ethereum/mist/releases
Solidity http://solidity.readthedocs.io/en/latest/
Web3 api https://github.com/ethereum/wiki/wiki/JavaScript-API
Community discussions https://www.reddit.com/r/ethereum/


If you have any issues regarding this article, you can raise it at our Github under the nightlyHacks repo.


와우. atomrigs 님 블로그에 있는 추천 글을 보고, 무작정 읽어 보며 글을 따라 갔는데... 역시 쉽지 않습니다.







매거진의 이전글 그런데, 블록체인 기술을 사용하면 뭐가 좋을까요?

매거진 선택

키워드 선택 0 / 3 0
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari
;