github.com/MetalBlockchain/metalgo@v1.11.9/version/compatibility.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package version 5 6 import ( 7 "errors" 8 "time" 9 10 "github.com/MetalBlockchain/metalgo/utils/timer/mockable" 11 ) 12 13 var ( 14 errIncompatible = errors.New("peers version is incompatible") 15 16 _ Compatibility = (*compatibility)(nil) 17 ) 18 19 // Compatibility a utility for checking the compatibility of peer versions 20 type Compatibility interface { 21 // Returns the local version 22 Version() *Application 23 24 // Returns nil if the provided version is compatible with the local version. 25 // This means that the version is connectable and that consensus messages 26 // can be made to them. 27 Compatible(*Application) error 28 } 29 30 type compatibility struct { 31 version *Application 32 33 minCompatible *Application 34 minCompatibleTime time.Time 35 prevMinCompatible *Application 36 37 clock mockable.Clock 38 } 39 40 // NewCompatibility returns a compatibility checker with the provided options 41 func NewCompatibility( 42 version *Application, 43 minCompatible *Application, 44 minCompatibleTime time.Time, 45 prevMinCompatible *Application, 46 ) Compatibility { 47 return &compatibility{ 48 version: version, 49 minCompatible: minCompatible, 50 minCompatibleTime: minCompatibleTime, 51 prevMinCompatible: prevMinCompatible, 52 } 53 } 54 55 func (c *compatibility) Version() *Application { 56 return c.version 57 } 58 59 func (c *compatibility) Compatible(peer *Application) error { 60 if err := c.version.Compatible(peer); err != nil { 61 return err 62 } 63 64 if !peer.Before(c.minCompatible) { 65 // The peer is at least the minimum compatible version. 66 return nil 67 } 68 69 // The peer is going to be marked as incompatible at [c.minCompatibleTime]. 70 now := c.clock.Time() 71 if !now.Before(c.minCompatibleTime) { 72 return errIncompatible 73 } 74 75 // The minCompatible check isn't being enforced yet. 76 if !peer.Before(c.prevMinCompatible) { 77 // The peer is at least the previous minimum compatible version. 78 return nil 79 } 80 return errIncompatible 81 }