2020-08-19 05:23:00 -07:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
2021-08-03 11:03:00 -07:00
|
|
|
gossipv1 "github.com/certusone/wormhole/bridge/pkg/proto/gossip/v1"
|
2020-08-19 05:23:00 -07:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2021-08-07 12:48:41 -07:00
|
|
|
"google.golang.org/protobuf/proto"
|
2021-07-31 09:51:38 -07:00
|
|
|
"sync"
|
2020-08-19 05:23:00 -07:00
|
|
|
)
|
|
|
|
|
2021-08-03 11:03:00 -07:00
|
|
|
// MaxGuardianCount specifies the maximum number of guardians supported by on-chain contracts.
|
|
|
|
//
|
2020-11-19 03:53:19 -08:00
|
|
|
// Matching constants:
|
2021-01-11 06:07:24 -08:00
|
|
|
// - MAX_LEN_GUARDIAN_KEYS in Solana contract (limited by transaction size - 19 is the maximum amount possible)
|
2020-11-19 03:53:19 -08:00
|
|
|
//
|
2021-01-11 06:07:24 -08:00
|
|
|
// The Eth and Terra contracts do not specify a maximum number and support more than that,
|
2020-11-19 03:53:19 -08:00
|
|
|
// but presumably, chain-specific transaction size limits will apply at some point (untested).
|
|
|
|
const MaxGuardianCount = 19
|
|
|
|
|
2020-08-19 05:23:00 -07:00
|
|
|
type GuardianSet struct {
|
2021-01-20 15:59:50 -08:00
|
|
|
// Guardian's public key hashes truncated by the ETH standard hashing mechanism (20 bytes).
|
2020-08-19 05:23:00 -07:00
|
|
|
Keys []common.Address
|
|
|
|
// On-chain set index
|
|
|
|
Index uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GuardianSet) KeysAsHexStrings() []string {
|
|
|
|
r := make([]string, len(g.Keys))
|
|
|
|
|
|
|
|
for n, k := range g.Keys {
|
|
|
|
r[n] = k.Hex()
|
|
|
|
}
|
|
|
|
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
2021-08-03 11:03:00 -07:00
|
|
|
// KeyIndex returns a given address index from the guardian set. Returns (-1, false)
|
2020-08-19 05:23:00 -07:00
|
|
|
// if the address wasn't found and (addr, true) otherwise.
|
|
|
|
func (g *GuardianSet) KeyIndex(addr common.Address) (int, bool) {
|
|
|
|
for n, k := range g.Keys {
|
|
|
|
if k == addr {
|
|
|
|
return n, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1, false
|
|
|
|
}
|
2021-07-31 09:51:38 -07:00
|
|
|
|
|
|
|
type GuardianSetState struct {
|
|
|
|
mu sync.Mutex
|
|
|
|
current *GuardianSet
|
2021-08-03 11:03:00 -07:00
|
|
|
|
|
|
|
// Last heartbeat message received per guardian. Maintained
|
|
|
|
// across guardian set updates - these values don't change.
|
|
|
|
lastHeartbeat map[common.Address]*gossipv1.Heartbeat
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewGuardianSetState() *GuardianSetState {
|
|
|
|
return &GuardianSetState{
|
|
|
|
lastHeartbeat: map[common.Address]*gossipv1.Heartbeat{},
|
|
|
|
}
|
2021-07-31 09:51:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (st *GuardianSetState) Set(set *GuardianSet) {
|
|
|
|
st.mu.Lock()
|
|
|
|
defer st.mu.Unlock()
|
|
|
|
|
|
|
|
st.current = set
|
|
|
|
}
|
|
|
|
|
|
|
|
func (st *GuardianSetState) Get() *GuardianSet {
|
|
|
|
st.mu.Lock()
|
|
|
|
defer st.mu.Unlock()
|
|
|
|
|
|
|
|
return st.current
|
|
|
|
}
|
2021-08-03 11:03:00 -07:00
|
|
|
|
|
|
|
// LastHeartbeat returns the most recent heartbeat message received for
|
|
|
|
// a given guardian node, or nil if none have been received.
|
|
|
|
func (st *GuardianSetState) LastHeartbeat(addr common.Address) *gossipv1.Heartbeat {
|
|
|
|
st.mu.Lock()
|
|
|
|
defer st.mu.Unlock()
|
|
|
|
return st.lastHeartbeat[addr]
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetHeartBeat stores a verified heartbeat observed by a given guardian.
|
|
|
|
func (st *GuardianSetState) SetHeartBeat(addr common.Address, hb *gossipv1.Heartbeat) {
|
|
|
|
st.mu.Lock()
|
|
|
|
defer st.mu.Unlock()
|
|
|
|
st.lastHeartbeat[addr] = hb
|
|
|
|
}
|
2021-08-07 12:48:41 -07:00
|
|
|
|
|
|
|
// GetAll returns all stored heartbeats.
|
|
|
|
func (st *GuardianSetState) GetAll() map[common.Address]*gossipv1.Heartbeat {
|
|
|
|
st.mu.Lock()
|
|
|
|
defer st.mu.Unlock()
|
|
|
|
|
|
|
|
ret := make(map[common.Address]*gossipv1.Heartbeat)
|
|
|
|
|
|
|
|
// Deep copy
|
|
|
|
for k, v := range st.lastHeartbeat {
|
|
|
|
ret[k] = proto.Clone(v).(*gossipv1.Heartbeat)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|