-
Notifications
You must be signed in to change notification settings - Fork 22
/
deposit_retrieval.go
123 lines (107 loc) · 4.17 KB
/
deposit_retrieval.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package utils
import (
"bytes"
"encoding/binary"
"math/big"
"sort"
"sync"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/rocket-pool/node-manager-core/beacon"
"github.com/rocket-pool/rocketpool-go/v2/core"
"github.com/rocket-pool/rocketpool-go/v2/rocketpool"
)
// BeaconDepositEvent represents a DepositEvent event raised by the BeaconDeposit contract.
type BeaconDepositEvent struct {
Pubkey []byte `abi:"pubkey"`
WithdrawalCredentials []byte `abi:"withdrawal_credentials"`
Amount []byte `abi:"amount"`
Signature []byte `abi:"signature"`
Index []byte `abi:"index"`
Raw types.Log // Blockchain specific contextual infos
}
// Formatted Beacon deposit event data
type DepositData struct {
Pubkey beacon.ValidatorPubkey `json:"pubkey"`
WithdrawalCredentials common.Hash `json:"withdrawalCredentials"`
Amount uint64 `json:"amount"`
Signature beacon.ValidatorSignature `json:"signature"`
TxHash common.Hash `json:"txHash"`
BlockNumber uint64 `json:"blockNumber"`
TxIndex uint `json:"txIndex"`
}
// Gets all of the deposit contract's deposit events for the provided pubkeys
func GetDeposits(rp *rocketpool.RocketPool, pubkeys map[beacon.ValidatorPubkey]bool, startBlock *big.Int, intervalSize *big.Int, opts *bind.CallOpts) (map[beacon.ValidatorPubkey][]DepositData, error) {
// Get the deposit contract wrapper
casperDeposit, err := getCasperDeposit(rp, opts)
if err != nil {
return nil, err
}
// Create the initial map and pubkey lookup
depositMap := make(map[beacon.ValidatorPubkey][]DepositData, len(pubkeys))
// Get the deposit events
addressFilter := []common.Address{casperDeposit.Address}
topicFilter := [][]common.Hash{{casperDeposit.ABI.Events["DepositEvent"].ID}}
logs, err := GetLogs(rp, addressFilter, topicFilter, intervalSize, startBlock, nil, nil)
if err != nil {
return nil, err
}
// Process each event
for _, log := range logs {
depositEvent := new(BeaconDepositEvent)
err = casperDeposit.ContractImpl.UnpackLog(depositEvent, "DepositEvent", log)
if err != nil {
return nil, err
}
// Check if this is a deposit for one of the pubkeys we're looking for
pubkey := beacon.ValidatorPubkey(depositEvent.Pubkey)
_, exists := pubkeys[pubkey]
if exists {
// Convert the deposit amount from little-endian binary to a uint64
var amount uint64
buf := bytes.NewReader(depositEvent.Amount)
err = binary.Read(buf, binary.LittleEndian, &amount)
if err != nil {
return nil, err
}
// Create the deposit data wrapper and add it to this pubkey's collection
depositData := DepositData{
Pubkey: pubkey,
WithdrawalCredentials: common.BytesToHash(depositEvent.WithdrawalCredentials),
Amount: amount,
Signature: beacon.ValidatorSignature(depositEvent.Signature),
TxHash: log.TxHash,
BlockNumber: log.BlockNumber,
TxIndex: log.TxIndex,
}
depositMap[pubkey] = append(depositMap[pubkey], depositData)
}
}
// Sort deposits by time
for _, deposits := range depositMap {
if len(deposits) > 1 {
sortDepositData(deposits)
}
}
return depositMap, nil
}
// Sorts a slice of deposit data entries - lower blocks come first, and if multiple transactions occur
// in the same block, lower transaction indices come first
func sortDepositData(data []DepositData) {
sort.Slice(data, func(i int, j int) bool {
first := data[i]
second := data[j]
if first.BlockNumber == second.BlockNumber {
return first.TxIndex < second.TxIndex
}
return first.BlockNumber < second.BlockNumber
})
}
// Get contracts
var casperDepositLock sync.Mutex
func getCasperDeposit(rp *rocketpool.RocketPool, opts *bind.CallOpts) (*core.Contract, error) {
casperDepositLock.Lock()
defer casperDepositLock.Unlock()
return rp.GetContract("casperDeposit") // NOTE: NOT A CORE CONTRACT, DO SOMETHING SPECIAL WITH THIS
}