kaistshadow / blockchain-sim

Scalable blockchain simulator/emulator running on shadow simulator
MIT License
9 stars 1 forks source link

FF-4, FF-6 test #289

Closed tkdlqm2 closed 3 years ago

tkdlqm2 commented 3 years ago

FF-4 : client block receive test FF-6 : Transaction propagation test

Originally posted by @tkdlqm2 in https://github.com/kaistshadow/blockchain-sim/issues/272#issuecomment-813812039

tkdlqm2 commented 3 years ago

기능 테스트 구현 전, data/bcdnode* 디렉토리 셋팅에 대해 리펙토링과 개선을 해봄.

Before) 이 쉘 스크립트를 CMakeLists.txt에서 실행하도록 정의가 되어 있으며, 코드를 보면 difficulty_3 으로 하드코딩이 되어있음. 즉 실행전에 몇개의 노드를 시뮬레이션할지 알아야하며, dificulty 또한 알아야함. 즉 하드코딩으로 구성이 되어 있음.

#!/bin/bash

if [ $# -lt 1 ]; then
    echo "Fail: please given node number"
    exit
fi

echo "cleanup data start!"

rm -rf data/*
i=0
while [ $i -lt $1 ]; do
    echo "$i"
    mkdir -p data/bcdnode$i
    cp -r ../../../testlibs/dump/difficulty_3/bcdnode0/* ./data/bcdnode$i
    i=$(($i+1))
done

path="../../../testlibs/dump/difficulty_3"

cp -r $path/coinflip_hash.txt ./data
cp -r $path/key.txt ./data
cp -r $path/state.txt ./data

echo "Datadir Bootstrapping success!"

After) testlibs/clean_data.py 에서 구현이 되었으며, 소스코드는 다음과 같음.

import os
import sys

def exec_shell_cmd(cmd):
    if os.system(cmd) != 0:
        print("error while executing '%s'" % cmd)
        exit(-1)

def main():
    node_count = sys.argv[1]
    difficulty = sys.argv[2]
    my_path = sys.argv[3]

    try:
        command = "cd " + my_path + "; rm -rf data"
        exec_shell_cmd(command)
    except:
        pass

    for i in range(0,int(node_count)):
        command = "cd " + my_path + "; mkdir -p data/bcdnode" + str(i)
        exec_shell_cmd(command)
        command = "cp -r ./dump/difficulty_" + difficulty + "/bcdnode0/* " + my_path + "/data/bcdnode" + str(i)
        exec_shell_cmd(command)

    path = "./dump/difficulty_" + difficulty

    command = "cp -r " + path + "/coinflip_hash.txt " + my_path + "/data"
    exec_shell_cmd(command)
    command = "cp -r " + path + "/key.txt " + my_path + "/data"
    exec_shell_cmd(command)
    command = "cp -r " + path + "/state.txt " + my_path + "/data"
    exec_shell_cmd(command)

if __name__ == '__main__':
    main()

소스코드를 보면 sys.argv[] 로 diificulty와 node 갯수와 실행 중인 경로를 받아옴. 이 파이썬 스크립트는 xml 생성 과정에서 실행이 되며, xml 생성 시 유저에게 콘솔로 부터 diificulty와 node_count를 받는 과정이 있음. 이 과정 다음에 바로 이 파이썬 스크립트가 불림. 즉 Before에서 하드코딩으로만 구현할 수 밖에 없었던 스크립트 로직을 개선하여 유저의 콘솔로부터 바로 적용이 가능하도록 수정함.

tkdlqm2 commented 3 years ago
        if condition_count == 2:
            difficulty = str(input("Input difficulty(1/2/3) : "))
            if (difficulty == "1") | (difficulty == "2") | (difficulty == "3"):
                condition_count = 3
                # --------------------------------------------------------------------------------------------------------------
                # data/bcdnode* 들은 여기 로직에 의해 생성됨.
                # --------------------------------------------------------------------------------------------------------------
                my_path = utils.filter_testlibs_path(my_path)
                my_commnad = "cd " + my_path + "; python clean_data.py " + str(node_count) + " " + difficulty + " " + path
                exec_shell_cmd(my_commnad)
            else:
                print("Enter only one of them(1/2/3)")

위의 소스코드는 xml_modules.py 의 get_xmlfile() 함수의 일부분임. 해당 함수에서는 difficulty를 user의 콘솔로 부터 받아오며, 받고나서, clean_data.py 스크립트 파일을 쉘 명령을 진행함.

tkdlqm2 commented 3 years ago

FF-4 Monitor block propagation test 완료

시뮬레이션을 하면 each_node_block_list 리스트에는 Monitor 노드가 비트코인 노드들로 부터 전파 받은 블록들의 hash 값들이 담기게됨. [[hash1, hash2, hash3 ... ], [hash1, hash2, hash3 ... ], ... ] 리스트안에 리스트의 개수가 곧 비트코인 노드의 개수와 같음. 테스트는 4번째 for문에서 진행이 되며, bitcoind 결과 로그 파일로 부터 updatetip에 기록된 블록 hash 값과 each_node_block_list에 담긴 노드들이 전파한 블록 hash 값들을 비교를함. 즉, 각 노드가 Monitor 노드에게 블록을 제대로 전파를 했는지 테스트 하는 것임.

def Mointor_block_propagation_test(plugin_output_files, node_count, target_path):
    each_node_block_list = utils.filter_block_hash(plugin_output_files, node_count)
    monitor_result_path = target_path + "/shadow.data/monitor_result.txt"
    f = open(monitor_result_path, "w")
    for i in range(len(each_node_block_list)):
        f.write("\t\t ---------- %d node monitor result ---------- \n\n" %i)
        for j in range(len(each_node_block_list[i])):
            f.write("Num %d block - %s\n" %(j, each_node_block_list[i][j]))
        f.write("\n")
    f.close()

    node_blocklist = []
    for i in range(node_count):
        line = []
        node_blocklist.append(line)

    for i in range(0,len(plugin_output_files)):
        result = plugin_output_files[i].find("stdout-bcdnode")
        if result != -1:
            node_blocklist[i] = test_result.filter_overlap_height(plugin_output_files[i])

    for i in range(0,len(node_blocklist)):
        for j in range(0,len(node_blocklist[i])-1):
            # 모니터 노드에는 제네시스 블록이 등록이 안되어 있기에, (전파된 블록만 컨트롤) 
            if node_blocklist[i][j+1][0] in each_node_block_list[i]:
                pass
            else:
                print("Fail Monitor block propagation test ... ")
                print("There is no block (%s) " %node_blocklist[i][j+1][0])
                sys.exit(1)
    print("Success Monitor block propagation test ... ")
    sys.exit(0)
tkdlqm2 commented 3 years ago

위와 같은 에러 사항으로 인해 FF-06 기능 테스트는 rel 0.3.0으로 미룰 것. 이는 Latency 측정에 필요한 기능으로서, rel0.2.0에는 안 다루기에.