git.pirl.io/community/pirl@v0.0.0-20201111064343-9d3d31ff74be/core/pirlguard.go (about) 1 package core 2 3 import ( 4 "errors" 5 "git.pirl.io/community/pirl/core/types" 6 "git.pirl.io/community/pirl/log" 7 "git.pirl.io/community/pirl/params" 8 "sort" 9 ) 10 11 var syncStatus bool 12 //var maxReorgValue = 5 13 //var maxChangedHashes = 3 14 15 func (bc *BlockChain) checkChainForAttack(blocks types.Blocks) error { 16 // Copyright 2014 The go-ethereum Authors 17 // Copyright 2018 Pirl Blockchain LTD 18 // This file is part of the go-ethereum library modified with Pirl Security Protocol. 19 // 20 // The go-ethereum library is free software: you can redistribute it and/or modify 21 // it under the terms of the GNU Lesser General Public License as published by 22 // the Free Software Foundation, either version 3 of the License, or 23 // (at your option) any later version. 24 // 25 // The go-ethereum library is distributed in the hope that it will be useful, 26 // but WITHOUT ANY WARRANTY; without even the implied warranty of 27 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 // GNU Lesser General Public License for more details. 29 // 30 // You should have received a copy of the GNU Lesser General Public License 31 // along with the go-ethereum library. If not, see http://www.gnu.org/licenses/. 32 // Package core implements the Ethereum consensus protocol modified with Pirl Security Protocol. 33 34 err := errors.New("") 35 err = nil 36 timeMap := make(map[uint64]int64) 37 tipOfTheMainChain := bc.CurrentBlock().NumberU64() 38 39 40 41 if !syncStatus { 42 if tipOfTheMainChain == blocks[0].NumberU64() - 1 { 43 //fmt.Println("We are synced") 44 syncStatus = true 45 } else { 46 //fmt.Println("Still syncing!") 47 syncStatus = false 48 } 49 } 50 //counter := 0 51 52 if len(blocks) > 0 && bc.CurrentBlock().NumberU64() > uint64(params.PirlGuardActivationBlock) { 53 //if syncStatus && len(blocks) < int(params.PirlGuardBlockLength) && len(blocks) > maxReorgValue { 54 // //fmt.Println("We are in the condition here to check smaller block sizes...") 55 // for _, b := range blocks { 56 // //fmt.Println("This is the tx hash from incoming block : ",b.NumberU64()," with hash : " , b.Header().Hash().String()) 57 // block := bc.GetBlockByNumber(b.NumberU64()) 58 // if block != nil { 59 // //fmt.Println("This is the tx hash from db block : ",block.NumberU64()," with hash : " , block.Header().Hash().String()) 60 // if b.Header().Hash().String() != block.Header().Hash().String() { 61 // counter++ 62 // //fmt.Println("block tx hashes dont match for block : ", block.NumberU64()) 63 // } 64 // } else { 65 // fmt.Println("block not found in db : ", b.NumberU64()) 66 // } 67 // fmt.Println("Matching blocks with changed hashes : ", counter) 68 // } 69 // if counter > maxChangedHashes { 70 // fmt.Println("big reorg detected") 71 // return ErrBigReorg 72 // } 73 //} 74 if syncStatus && len(blocks) >= int(params.PirlGuardBlockLength) { 75 for _, b := range blocks { 76 timeMap[b.NumberU64()] = calculatePenaltyTimeForBlock(tipOfTheMainChain, b.NumberU64()) 77 } 78 } 79 } 80 81 p := make(PairList, len(timeMap)) 82 index := 0 83 for k, v := range timeMap { 84 p[index] = Pair {k, v} 85 index++ 86 } 87 sort.Sort(p) 88 var penalty int64 89 for _, v := range p { 90 penalty += v.Value 91 } 92 93 multi := calculateMulti(bc.CurrentBlock().Difficulty().Uint64()) 94 penalty = penalty * int64(multi) 95 96 if penalty < 0 { 97 penalty = 0 98 } 99 //fmt.Println("Penalty value for the chain :", penalty) 100 context := []interface{}{ 101 "synced", syncStatus, "number", tipOfTheMainChain, "incoming_number", blocks[0].NumberU64() - 1, "penalty", penalty ,"implementation", "The Pirl Team", 102 } 103 104 log.Info("checking legitimity of the chain", context... ) 105 106 if penalty > 0 { 107 context := []interface{}{ 108 "penalty", penalty, 109 } 110 log.Error("Chain is a malicious and we should reject it", context... ) 111 err = ErrDelayTooHigh 112 113 } 114 115 if penalty == 0 { 116 err = nil 117 } 118 119 return err 120 } 121 122 func calculatePenaltyTimeForBlock(tipOfTheMainChain , incomingBlock uint64) int64 { 123 if incomingBlock < tipOfTheMainChain { 124 return int64(tipOfTheMainChain - incomingBlock) 125 } 126 if incomingBlock == tipOfTheMainChain { 127 return 0 128 } 129 if incomingBlock > tipOfTheMainChain { 130 return -1 131 } 132 return 0 133 } 134 135 func calculateMulti(diff uint64) uint64 { 136 137 if diff <= 500000000 { 138 return 5 139 } 140 if diff >= 500000000 && diff < 20000000000 { 141 return 4 142 } 143 if diff >= 20000000000 && diff < 30000000000 { 144 return 3 145 } 146 if diff >= 30000000000 && diff < 50000000000 { 147 return 2 148 } 149 if diff >= 50000000000 { 150 return 1 151 } 152 return 1 153 } 154 155 // A data structure to hold key/value pairs 156 type Pair struct { 157 Key uint64 158 Value int64 159 } 160 161 // A slice of pairs that implements sort.Interface to sort by values 162 type PairList []Pair 163 164 func (p PairList) Len() int { return len(p) } 165 func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 166 func (p PairList) Less(i, j int) bool { return p[i].Key < p[j].Key }