1. 주요 기능
2. 사용 기술
3. 아키텍처 및 흐름도
4. 개발
4-1. 코드
4-2. 화면
5. 평가
6. 결과
- 스마트 컨트랙트 업로드
- 스마트 컨트랙트 대시보드 - 스마트 컨트랙트 검색 / 비교
- 스마트 컨트랙트 상세 정보 - 설치 / 다운로드 / 트랜잭션
- 프론트 : React(Typescript)
- 백엔드 : Gin(Golang)
- 검색 엔진 & 스토리지 : Elastic Search
- 블록체인 : Hyperledger Fabric, Fabric Gateway SDK
- 테스트 : Jmeter, Postman
아키텍처 | 흐름도 |
---|---|
func SetConnection() {
log.Println("===============Set Connection ===============")
clientConnection := newGrpcConnection()
//defer clientConnection.Close()
id := newIdentity()
sign := newSign()
gateway, err := client.Connect(
id,
client.WithSign(sign),
client.WithClientConnection(clientConnection),
client.WithEvaluateTimeout(5*time.Second),
client.WithEndorseTimeout(15*time.Second),
client.WithSubmitTimeout(5*time.Second),
client.WithCommitStatusTimeout(1*time.Minute),
)
if err != nil {
panic(err)
}
//defer gateway.Close()
network := gateway.GetNetwork(channelName)
ContractPass = network.GetContract(chaincodeName)
}
func TransferAsset(contract *client.Contract, transactionRequest TransactionRequest) string {
log.Println(contract, "2", transactionRequest.AssetID, transactionRequest.NewOwner)
submitResult, commit, err := contract.SubmitAsync("TransferAsset", client.WithArguments(transactionRequest.AssetID, transactionRequest.NewOwner))
if err != nil {
panic(fmt.Errorf("failed to submit transaction asynchronously: %w", err))
}
fmt.Printf("Successfully submitted transaction to transfer ownership from %s to %s. \n", string(submitResult), transactionRequest.NewOwner)
if status, err := commit.Status(); err != nil {
panic(fmt.Errorf("failed to get commit status: %w", err))
} else if !status.Successful {
panic(fmt.Errorf("transaction %s failed to commit with status: %d", status.TransactionID, int32(status.Code)))
}
return string(submitResult)
}
type elasticClient struct {
es *elasticsearch.Client
IndexName string
}
type ESResponse struct {
Took int64
Hits struct {
Total struct {
Value int64
}
Hits []*ESHit
}
}
type ESHit struct {
Score float64 `json:"_score"`
Index string `json:"_index"`
Type string `json:"_type"`
Version int64 `json:"_version,omitempty"`
Source Article `json:"_source"`
}
func init() {
cfg := esClientConfig()
es, err := elasticsearch.NewClient(cfg)
if err != nil {
log.Printf("Error creating the client: %s", err)
} else {
log.Println(elasticsearch.Version)
log.Println(es.Info())
}
esClient.es = es
esClient.IndexName = "smart_contract"
}
func esClientConfig() elasticsearch.Config {
cfg := elasticsearch.Config{
Addresses: []string{"https://localhost:9200"},
APIKey: "ZkkwZ2dvWUJvNHBGMlQzZXVGZUU6eGJGaHpTY0JTWC1IU2ZvOTdHTk16QQ==",
CertificateFingerprint: "6a220394bb428259b1991b3dcce16f7a810499de023d5d0bdb97c32bd762ba14",
}
//password : Zh-rgUV*3rdM6NhQE+Bo
return cfg
}
func AddDocumentToES(item *Article) (string, error) {
payload, err := json.Marshal(item)
if err != nil {
log.Println(err)
return "", err
}
ctx := context.Background()
req := esapi.IndexRequest{
Index: esClient.IndexName,
DocumentID: string(item.ID),
Body: bytes.NewReader(payload),
Refresh: "true",
}
res, err := req.Do(ctx, esClient.es)
if err != nil {
log.Fatalf("Error getting rsponse: %s", err)
}
defer res.Body.Close()
if res.IsError() {
var e map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
log.Print("payload : ")
log.Println(e)
log.Println(err)
return "", err
}
log.Print(e)
return "", fmt.Errorf("[%s] %s: %s", res.Status(),
e["error"].(map[string]interface{})["type"],
e["error"].(map[string]interface{})["reason"])
}
return "Contract successfully added to search index", nil
}
정보 | |
---|---|
스마트 컨트랙트 |
|
스마트 컨트랙트 |
|
스마트 컨트랙트 |
|
스마트 컨트랙트 |
|
트랜잭션 |
본 프로젝트에서는 하이퍼레저 패브릭 네트워크와 연결하기 위해 Fabric Gateway SDK를 활용하였으며,
명령어 기반 실행과 SDK 기반 트랜잭션 성능을 평가하였다.
- SDK
- 플랫폼과 연결하는 시간은 포함되지 않음.
- REST API 요청 ->응답 사이의 시간을 측정하였음.
- Jmeter를 활용
- CLI
- 시간 측정은 서버에서 CLI를 통해 쉘스크립트에 작성된 명령어 set을 실행하는 것으로 소요 시간 측정
- 반복문-쉘스크립트 -> 동작-쉘스크립트 형태로 반복 수행하였음.
- 데이터는 파이프라인을 통해 기록하고 이를 쉘스크립트를 통해 min,avg,max 로 종합, 정리함.
- CLI 첫 값의 latency가 매우 큼
- 아마 connection 문제일 듯, Gateway는 connection pool이 존재함.
- 99% line의 값과 maximum값의 차이가 매우 큼, 이는 한 값이 매우 튐을 추측할 수 있음.
- => 결과적으로 첫 번째 튀는 값을 제외한 나머지들을 통해서 min,avg,max 값을 평가함.
전체 비교 |
최대 |
평균 |
최소 |
- SDK가 CLI보다 성능이 뛰어남.
- 이유
- Fabric Gateway SDK의 경우 connection pooling 방식을 통해 패브릭 네트워크와 연결되어있음.
- 그러나, CLI의 경우 매번 독립적으로 시행되기 때문에 매번 패브릭 네트워크와 연결하는 것으로 추측