전체 블록 구조
8
blockfile_mgr.go
func(mgr *blockfileMgr) addBlock(block *common.Block) error {
...
blockBytesLen := len(blockBytes)
blockBytesEncodedLen := proto.EncodeVarint(uint64(blockBytesLen))
totalBytesToAppend := blockBytesLen + len(blockBytesEncodedLen)
...
//append blockBytesEncodedLen to the file
err = mgr.currentFileWriter.append(blockBytesEncodedLen, false)
if err == nil {
//append the actual block bytes to the file
err = mgr.currentFileWriter.append(blockBytes, true)
}
• 블록 길이를 먼저 쓰고 블록 데이터를 쓰는 코드를 보면 가변 블록 구조임을 파악할 수 있음
• EncodeVarint 는 프로토콜 버퍼의 정수 인코딩이므로, 단지 gRPC 뿐 아니라 블록 파일에서도 프로토콜 버퍼를 광범위하게 사용할 것이라는
사실을 이 시점에서 추정 가능
9.
프로토콜 버퍼 인코딩
9
https://developers.google.com/protocol-buffers/docs/encoding
메모리의정수 표현 디스크, 네트워크 입출력 시 정수 표현
int16
int32
int64
1 2
1 2 3 4
1 2 3 4 5 6 7 8
varint 0000 00011 =
300 = 1010 1100 0000 0010
10 0101100(2) = 300(10)
• 메모리에서는 일반적으로 고정 길이 공간을 사용하여 수치형을 표현합니다.
• 디스크, 네트워크 전송 시에는 I/O 대역폭 및 저장 공간 점유를 최소화하기 위해 가변 길이 인코딩을 일반적으로 사용합니다.
• VarInt (Variable-length Integer) 는 고전적인 가변 길이 인코딩 방식으로, 가장 앞 비트 (MSB)를 뒷 바이트가 이어진다는 신호로 사용하고
7비트를 이어 붙여서 전체 데이터를 표현합니다.
• 패브릭 프로토콜 버퍼는 Little Endian 기준이라 7비트 그룹을 역순으로 조립해야 합니다.
- 예를 들어 정수 300은 000 0010 010 1100 처럼 이어붙여서 해석합니다.
10.
프로토콜 버퍼 인코딩
10
https://developers.google.com/protocol-buffers/docs/encoding
타입별인코딩 방식
타입번호 의미 타입 매핑
0 VarInt int32, int64, uint64, sint32, sint64, bool, enum
1 64비트 fixed64, sfixed64, double
2 길이 지정 string, bytes, embedded message, packed repeated fields
3 그룹 시작 groups (폐기됨)
4 그룹 끝 groups (폐기됨)
5 32비트 fixed32, sfixed32, float
길이 지정 인코딩 예시 (문자열)
복합 메시지 예시
07 74 65 73 74 69 6e 67"testing"
7글자 t e s t i n g
message Test2 {
optional string b = 2;
}
07 74 65 73 74 69 6e 67
7글자 t e s t i n g
12
메타
00010 010
2번 필드 2번 타입
• 아쉽게도 message (complex type)와
bytes, string 의 타입 구분이 안 되어서
메타데이터 정의 없이 파싱하는 것은
원천적으로 불가능
• 필드 번호를 지정하므로 optional 구현
은 간단하고 효율적임.
11.
1번 블록 구조
11
{
"header":{
"channel_header": {
"type": 1,
"channel_id": "mychannel",
"timestamp": "2018-08-20 01:12:48+0900"
}
"signature_header": {
"creator": {
"mspid": "OrdererMSP",
"id_bytes": "-----BEGIN CERTIFICATE-----
nMIICDDCCAbOgAwIBAgIRAK30hdRcBxQJYNPqPkiFo3IwCgYIKoZIzj0EAwIwaTELnMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGncmFuY2lzY
28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFtncGxlLmNvbTAeFw0xNzA4MzEwOTE0MzJaFw0yNzA4MjkwOTE0MzJaMFgxCzAJBgNVnBAYTAlVTMRMwEQ
YDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpnc2NvMRwwGgYDVQQDExNvcmRlcmVyLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYInKoZIzj0DAQcDQgAE
UOJGzpasxjS5EJmbFIe/GtOJJAo6mhJqLyYT9PBvVSdaQ/TQnlMNlqLEZgFP6wc9CtrUp/WDnZ/M2zLpoDPjkcqNNMEswDgYDVR0PAQH/BAQDAgeAnMAwGA1UdEwEB/wQCMAAwKwYD
VR0jBCQwIoAgoGBqSoYKHjHJCiN4jabztrdJJe0NnIwYa9ImUCbpGrmowCgYIKoZIzj0EAwIDRwAwRAIgHsU1f4jzuul6zYGY/Xn/H5X5ngDe7/u8dZxJfWwXOGNsCICbXt6yezSzacOFQDkvAP
z5/3OYI5YKLSTl+Wilfa/qyn-----END CERTIFICATE-----n"
},
"nonce": "ef86bebfe565f8aed0c60994bd480fd013bd77808f65a554"
},
},
"data": "..미 해석 영역.."
}
헤더 타입 ENUM 설명
0 MESSAGE 서명된 메시지이나 데이터 구조가 알려지지 않은 것
1 CONFIG 채널 설정 메시지
2 CONFIG_UPDATE 채널 설정 업데이트 트랜잭션
3 ENDORSER_TRANSACTION Endorser 기반 트랜잭션 제출 (SDK에서 사용)
4 ORDERER_TRANSACTION Orderer가 사용하는 관리용 메시지
5 DELIVER_SEEK_INFO Deliver API의 Envelope 메시지 탐색 제어용
6 CHAINCODE_PACKAGE 설치 시 체인코드 패키징에 사용
8 PEER_ADMIN_OPERATION Peer에서 수행되는 관리적 작업 호출
HeaderType 정의 (protos/common/common.proto)
12.
체인코드 트랜잭션 수행흐름 proposal.proto 참조
12
Client Endorser
Client Endorser
1
2
Client Orderer
3
이 proposal에 대한 action
전체 응답 페이로드에 대한 Endorser의 서명들
action을 요청한 proposal의 페이로드
action을 요청한 proposal의 헤더
헤더의 creator가 Transaction 에 대해 수행한 서명
전체 응답 페이로드에 대한 Endorser의 서명
이 proposal에 대한 action
이 proposal에 대한 action (생략 가능)
이 proposal의 페이로드
이 proposal의 헤더
헤더의 creator가 proposal 에 대해 수행한 서명
• 클라이언트는 1개 이상의 proposal을 모아서 하나의 트랜잭션 메
시지를 생성하고 이를 orderer에게 전송합니다.
• orderer는 여러 개의 트랜잭션을 배치 단위로 commiting peer에게
전달(deliver)합니다. committing peer는 검증 후 원장에 반영합니
다.
• 트랜잭션은 1개 이상의 action으로 구성되고, 각각 헤더, 제안
(proposal) 페이로드, 서명된 응답 페이로드 (response)를 포함합니
다.
• 응답은 성공/실패 코드, 응답 페이로드, 응답 페이로드에 대한
서명으로 구성됩니다.
• 응답 페이로드는 요청 (proposal)에 대한 해시를 포함합니다.
이는 특정 요청에 대한 응답을 안전하게 매핑할 목적입니다.
• proposal은 체인코드를 실행해달라는 요청입니다.
- 체인코드의 상태 변경 및 원장에 데이터 반영
• proposal은 헤더와 페이로드로 구성됩니다.
- 헤더: 타입, 실행요청자, 시각, 체인ID, Nonce
- 페이로드: 체인코드ID, 호출 매개변수
13.
2번 블록 구조- 헤더
13
{
"header": {
"channel_header": {
"type": 3,
"timestamp": "2018-08-20 01:12:51+0900",
"channel_id": "mychannel",
"tx_id": "bc395ae86abbc9b75aa41b998bf2d0f4cf4e78af2bd59c20a455965d498675c2",
"extension": "120612046c736363"
},
"signature_header": {
"creator": {
"mspid": "Org1MSP",
"id_bytes": "-----BEGIN CERTIFICATE-----
nMIICGDCCAb+gAwIBAgIQFSxnLAGsu04zrFkAEwzn6zAKBggqhkjOPQQDAjBzMQswnCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZynYW5
jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eunb3JnMS5leGFtcGxlLmNvbTAeFw0xNzA4MzEwOTE0MzJaFw0yNzA4MjkwOTE0MzJanMFsxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TnYW4gRnJhbmNpc2NvMR8wHQYDVQQDDBZBZG1pbkBvcmcxLmV4YW1wbGUuY29tMFkwnEwYHKoZIzj0C
AQYIKoZIzj0DAQcDQgAEV1dfmKxsFKWo7o6DNBIaIVebCCPAM9C/nsLBt4pJRre9pWE987DjXZoZ3glc4+DoPMtTmBRqbPVwYcUvpbYY8p6NNMEswDgYDnVR0PAQH/BAQDAgeAMAwG
A1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgQjmqDc122u64nugzacBhR0UUE0xqtGy3d26xqVzZeSXwwCgYIKoZIzj0EAwIDRwAwRAIgXMy26AEUn/GUMPfCMs/nQjQME1ZxBHAYZtKEu
RR361JsCIEg9BOZdIoioRivJC+ZUzvJUnkXuno2HkWiuxLsibGxtEn-----END CERTIFICATE-----n"
},
"nonce": "998d2b96865a56bda70c0e09a2acefa6e9cad8015ee17d6a"
}
},
"tx_actions": [ .... ]
}
헤더 타입 ENUM 설명
0 MESSAGE 서명된 메시지이나 데이터 구조가 알려지지 않은 것
1 CONFIG 채널 설정 메시지
2 CONFIG_UPDATE 채널 설정 업데이트 트랜잭션
3 ENDORSER_TRANSACTION Endorser 기반 트랜잭션 제출 (SDK에서 사용)
4 ORDERER_TRANSACTION Orderer가 사용하는 관리용 메시지
5 DELIVER_SEEK_INFO Deliver API의 Envelope 메시지 탐색 제어용
6 CHAINCODE_PACKAGE 설치 시 체인코드 패키징에 사용
8 PEER_ADMIN_OPERATION Peer에서 수행되는 관리적 작업 호출
HeaderType 정의 (protos/common/common.proto)