github.com/annchain/OG@v0.0.9/og/verifier/graph_verifier.go (about) 1 package verifier 2 3 import ( 4 types2 "github.com/annchain/OG/arefactor/og/types" 5 "github.com/annchain/OG/og" 6 "github.com/annchain/OG/og/protocol/ogmessage/archive" 7 "github.com/annchain/OG/og/types" 8 "github.com/annchain/OG/ogcore/pool" 9 10 "github.com/annchain/OG/status" 11 "github.com/sirupsen/logrus" 12 ) 13 14 // GraphVerifier verifies if the tx meets the OG hash and graph standards. 15 type GraphVerifier struct { 16 Dag og.IDag 17 TxPool pool.ITxPool 18 //Buffer *TxBuffer 19 } 20 21 func (c *GraphVerifier) String() string { 22 return c.Name() 23 } 24 func (v *GraphVerifier) Independent() bool { 25 return false 26 } 27 28 func (v *GraphVerifier) Name() string { 29 return "GraphVerifier" 30 } 31 32 // getTxFromTempSource tries to get tx from anywhere but dag itself. 33 // return nil if not found in either txpool or buffer 34 func (v *GraphVerifier) getTxFromTempSource(hash types2.Hash) (txi types.Txi) { 35 // Re-think. Do we really need to check buffer? 36 37 //if v.Buffer != nil { 38 // txi = v.Buffer.GetFromBuffer(hash) 39 // if txi != nil { 40 // return 41 // } 42 //} 43 44 if v.TxPool != nil { 45 txi = v.TxPool.Get(hash) 46 if txi != nil { 47 return 48 } 49 } 50 return 51 } 52 53 func (v *GraphVerifier) getTxFromAnywhere(hash types2.Hash) (txi types.Txi, archived bool) { 54 txi = v.getTxFromTempSource(hash) 55 if txi != nil { 56 archived = false 57 return 58 } 59 if v.Dag != nil { 60 txi = v.Dag.GetTx(hash) 61 if txi != nil { 62 archived = true 63 return 64 } 65 } 66 return 67 } 68 69 // getMyPreviousTx tries to fetch the tx that is announced by the same source with nonce = current nonce -1 70 // return true if found, or false if not found in txpool or in dag 71 func (v *GraphVerifier) getMyPreviousTx(currentTx types.Txi) (previousTx types.Txi, ok bool) { 72 if currentTx.GetNonce() == 1 { 73 ok = true 74 return 75 } 76 seeked := map[types2.Hash]bool{} 77 seekingHashes := types2.Hashes{} 78 for _, parent := range currentTx.GetParents() { 79 seekingHashes = append(seekingHashes, parent) 80 } 81 82 if status.ArchiveMode { 83 if ptx := v.Dag.GetTxByNonce(currentTx.Sender(), currentTx.GetNonce()-1); ptx != nil { 84 previousTx = ptx 85 ok = true 86 return 87 } 88 return nil, false 89 } 90 91 for len(seekingHashes) > 0 { 92 head := seekingHashes[0] 93 seekingHashes = seekingHashes[1:] 94 95 txi, archived := v.getTxFromAnywhere(head) 96 if txi != nil { 97 // found. verify nonce 98 if txi.GetType() != types.TxBaseTypeArchive { 99 if txi.Sender() == currentTx.Sender() { 100 // verify if the nonce is larger 101 if txi.GetNonce() == currentTx.GetNonce()-1 { 102 // good 103 previousTx = txi 104 ok = true 105 return 106 } 107 } 108 } 109 110 switch txi.GetType() { 111 case types.TxBaseTypeSequencer: 112 // nothing to do, since all txs before seq should already be archived 113 default: 114 // may be somewhere else 115 // enqueue header more if we are still in the temp area 116 if archived { 117 continue 118 } 119 for _, parent := range txi.GetParents() { 120 if _, ok := seeked[parent]; !ok { 121 seekingHashes = append(seekingHashes, parent) 122 seeked[parent] = true 123 } 124 } 125 continue 126 127 } 128 } else { 129 // should not be here 130 logrus.WithField("current tx ", currentTx).WithField("ancestor", head).Warn("ancestor not found: should not be here.") 131 // this ancestor should already be in the dag. do nothing 132 } 133 } 134 135 //// Here, the ancestor of the same From address must be in the dag. 136 //// Once found, this tx must be the previous tx of currentTx because everyone behind sequencer is confirmed by sequencer 137 //if ptx := v.Dag.GetTxByNonce(currentTx.Sender(), currentTx.GetNonce()-1); ptx != nil { 138 // previousTx = ptx 139 // ok = true 140 // return 141 //} 142 //return 143 return 144 } 145 146 // get the nearest previous sequencer from txpool 147 func (v *GraphVerifier) getPreviousSequencer(currentSeq *types.Sequencer) (previousSeq *types.Sequencer, ok bool) { 148 seeked := map[types2.Hash]bool{} 149 seekingHashes := types2.Hashes{} 150 // seekingHashes := list.New() 151 seekingHashes = append(seekingHashes, currentSeq.GetHash()) 152 // seekingHashes.PushBack(currentSeq.GetHash()) 153 for len(seekingHashes) > 0 { 154 head := seekingHashes[0] 155 seekingHashes = seekingHashes[1:] 156 // head := seekingHashes.Remove(seekingHashes.Front()).(common.Hash) 157 txi, archived := v.getTxFromAnywhere(head) 158 159 if txi != nil { 160 switch txi.GetType() { 161 case types.TxBaseTypeSequencer: 162 // found seq, check nonce 163 // verify if the nonce is larger 164 if txi.(*types.Sequencer).Height == currentSeq.Height-1 { 165 // good 166 previousSeq = txi.(*types.Sequencer) 167 ok = true 168 return 169 } 170 default: 171 break 172 } 173 // may be somewhere else 174 // enqueue header more if we are still in the temp area 175 if archived { 176 continue 177 } 178 for _, parent := range txi.GetParents() { 179 if _, ok := seeked[parent]; !ok { 180 seekingHashes = append(seekingHashes, parent) 181 // seekingHashes.PushBack(parent) 182 seeked[parent] = true 183 } 184 } 185 } 186 } 187 // Here, the ancestor of the same From address must be in the dag. 188 // Once found, this tx must be the previous tx of currentTx because everyone behind sequencer is confirmed by sequencer 189 if ptx := v.Dag.GetSequencerByHeight(currentSeq.Height - 1); ptx != nil { 190 previousSeq = ptx 191 ok = true 192 return 193 } else { 194 logrus.Debug(ptx, currentSeq.Height-1) 195 } 196 197 return 198 } 199 200 // Verify do the graph validation according to the following rules that are marked as [My job]. 201 // Graph standards: 202 // A1: [My job] Randomly choose 2 tips. 203 // A2: [Not used] Node's parent cannot be its grandparents or ancestors. 204 // A3: [My job] Nodes produced by same source must be sequential (tx nonce ++). 205 // A4: [------] Double spending once A3 is not followed, whatever there is actual double spending. 206 // A5: [Pool's job] If A3 is followed but there is still double spending (tx nonce collision), keep the forked tx with smaller hash 207 // A6: [My job] Node cannot reference two un-ordered nodes as its parents 208 // B1: [My job] Nodes that are confirmed by at least N (=2) sequencers cannot be referenced. 209 // B2: [My job] Two layer hash validation 210 // Basically Verify checks whether txs are in their nonce order 211 func (v *GraphVerifier) Verify(txi types.Txi) (ok bool) { 212 //if txi.IsVerified().IsGraphVerified() { 213 // return true 214 //} 215 ok = false 216 if ok = v.verifyWeight(txi); !ok { 217 logrus.WithField("tx", txi).Debug("tx failed on weight") 218 return 219 } 220 if ok = v.verifyA3(txi); !ok { 221 logrus.WithField("tx", txi).Debug("tx failed on graph A3") 222 return 223 } 224 if ok = v.verifyB1(txi); !ok { 225 logrus.WithField("tx", txi).Debug("tx failed on graph B1") 226 return 227 } 228 if txi.GetType() == types.TxBaseTypeSequencer { 229 seq := txi.(*types.Sequencer) 230 if err := v.TxPool.IsBadSeq(seq); err != nil { 231 logrus.WithField("seq ", seq).WithError(err).Warn("bad seq") 232 return false 233 } 234 } 235 236 txi.SetVerified(archive.VerifiedGraph) 237 return true 238 } 239 240 func (v *GraphVerifier) verifyA3(txi types.Txi) bool { 241 // constantly check the ancestors until the same one issued by me is found. 242 // or nonce reaches 1 243 244 if txi.GetType() == types.TxBaseTypeArchive { 245 return true 246 } 247 if status.ArchiveMode { 248 if txi.GetType() != types.TxBaseTypeSequencer { 249 logrus.Warn("archive mode , only process archive") 250 return false 251 } 252 } 253 254 if txi.GetNonce() == 0 { 255 return false 256 } 257 var ok bool 258 259 // first tx check 260 nonce, poolErr := v.TxPool.GetLatestNonce(txi.Sender()) 261 if txi.GetNonce() == 1 { 262 // test claim: whether it should be 0 263 264 if poolErr == nil { 265 logrus.Debugf("nonce should not be 0. Latest nonce is %d and you should be larger than it", nonce) 266 } 267 // not found is good 268 return poolErr != nil 269 } 270 dagNonce, _ := v.Dag.GetLatestNonce(txi.Sender()) 271 if poolErr != nil { 272 //no related tx in txpool ,check dag 273 if dagNonce != txi.GetNonce()-1 { 274 logrus.WithField("current nonce ", txi.GetNonce()).WithField("dag nonce ", dagNonce).WithField("tx", txi).Debug("previous tx not found for address") 275 // fail if not good 276 return false 277 } 278 goto Out 279 } 280 if nonce < txi.GetNonce()-1 { 281 logrus.WithField("current nonce ", txi.GetNonce()).WithField("pool nonce ", nonce).WithField("tx", txi).Debug("previous tx not found for address") 282 // fail if not good 283 return false 284 } 285 // check txpool queue first 286 if dagNonce != nonce { 287 _, ok = v.getMyPreviousTx(txi) 288 if !ok { 289 logrus.WithField("tx", txi).Debug("previous tx not found") 290 // fail if not good 291 return ok 292 } 293 } 294 295 Out: 296 297 switch txi.GetType() { 298 // no additional check 299 case types.TxBaseTypeSequencer: 300 seq := txi.(*types.Sequencer) 301 // to check if there is a lower seq height in the path behind 302 _, ok = v.getPreviousSequencer(seq) 303 if !ok { 304 logrus.WithField("tx", txi).Debug("previous seq not found") 305 } 306 307 return ok 308 default: 309 } 310 return true 311 } 312 313 func (v *GraphVerifier) verifyB1(txi types.Txi) bool { 314 // compare the sequencer id 315 return true 316 } 317 318 func (v *GraphVerifier) verifyWeight(txi types.Txi) bool { 319 var parents types.Txis 320 for _, pHash := range txi.GetParents() { 321 parent := v.TxPool.Get(pHash) 322 if parent == nil { 323 parent = v.Dag.GetTx(pHash) 324 } 325 if parent == nil { 326 logrus.WithField("parent hash ", pHash).Warn("parent not found") 327 return false 328 } 329 parents = append(parents, parent) 330 } 331 return txi.CalculateWeight(parents) == txi.GetWeight() 332 }