kaistshadow / blockchain-sim

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

rel 0.2.0 reg test 중에 mainchain test 에 블록 포크 예외처리 추가 #274

Closed tkdlqm2 closed 3 years ago

tkdlqm2 commented 3 years ago

rel 0.2.0 reg test 중에 mainchain test의 고려 사항이 추가되었음. rel 0.2.0은 멀티 노드 환경이라, 블록 포크가 나는 상황을 고려를 해야함. 기존의 rel 0.1.0 test 통과 기준은 각 노드들의 마지막 블록 해시 값이 match rate이 100%면 통과하는 식으로 디자인 되었음. 하지만 블록 포크가 발생했을 시, match rate은 100%가 안됨으로 테스트가 통과가 안됨. 그렇기에 블록 포크에 대한 예외 처리를 추가를 해주어야함.

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

tkdlqm2 commented 3 years ago

bitcoin은 longest chain rule이고 디테일한 기준은 해당 블록이 인정을 받기 위해서 자식블록 6개가 먼저 생성이 되어야함. 즉 6개 블록이 생성이 되었음에도 불구하고 longest chain rule을 무시하고 계속해서 블록 포크가 발생한다면 분명한 에러임. 하지만 이런 극단적인 상황이 아니고, 블록 포크가 발생하는 경우는 자연스러운 상황임.

mainchain 테스트 시나리오

  1. 마지막 블록 해시 비교 2-1 모두 일치 - 통과 2-2 하나라도 불일치 - 블록 포크
  2. 마지막 이전 블록 해시 비교 3-1 모두 일치 - 블록 포크 상황으로 테스트 통과 3-2 불일치 - 마지막 이전전 블록 해시 비교 이 과정을 마지막 블록 기준 다섯번을 하고, 다섯번 블록 까지도 불일치 하면 네트워크 파티셔닝이 발생한 것임. (오류) 이런 상황은 결국 테스트 실패임.
tkdlqm2 commented 3 years ago
def get_last_hashValue(shadow_output_file, rpc_output_file, node_count, pork_count):
    condition_count = 0
    i = 0
    for z in range(0,node_count):
        f = open(rpc_output_file[z+node_count] , "r")
        for line in f.readlines()[::-1]:
            line.rstrip()
            result = line.find("bestblockhash")
            if result != -1:
                line = line.split(",")[3].split(":")[1]
                genesisHash = line[1:len(line)-1]
                i += 1
                if i == (pork_count+1):
                    break
                else:
                    continue

        if os.path.isfile(shadow_output_file[z]):
            f = open(shadow_output_file[z], "r")
            while True:
                line = f.readline()
                if not line: break
                result = line.find(genesisHash)
                if result != -1:
                    condition_count += 1

    return condition_count

마지막 블록 해시를 가져오게 하는 함수를 별도로 만들어서, 포크 발생 시 재귀적 호출을 통해 6번 이상의 호출이 될 경우 network separation이 발생했다고 간주하고 테스트 종료 (에러 리턴) 그 외에 5번 이하의 호출이면 단순 fork 발생으로 테스트 정상 종료.

def test_MainChainInfo(shadow_output_file, rpc_output_file, node_count):
    pork_count = 0
    while True:
        condition_count = utils.get_last_hashValue(shadow_output_file, rpc_output_file, node_count, pork_count)    
        if condition_count == node_count:
            break
        else:
            pork_count += 1

    if pork_count > 6:
        print("Fail mainchain test ... (network separation) ")
    elif pork_count == 0:
        pass
    else:
        print("There is a fork ...")
        condition_count = node_count

    test_result(condition_count, node_count, "mainchain test")
    sys.exit(0)