Skip to content

Commit 1f14f5f

Browse files
committed
feat: smooth transition for coston2
1 parent cc9e6d1 commit 1f14f5f

2 files changed

Lines changed: 182 additions & 36 deletions

File tree

client/epoch/epoch_client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ func NewClient(ctx flarectx.ClientContext) (*client, error) {
9999
cfg.ContractAddresses.VoterPreRegistry,
100100
senderTxOpts,
101101
signerPk,
102+
chainCfg.ChainID,
102103
)
103104
if err != nil {
104105
return nil, err

client/epoch/registry_utils.go

Lines changed: 181 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/ethereum/go-ethereum/accounts/abi"
1515
"github.com/ethereum/go-ethereum/accounts/abi/bind"
1616
"github.com/ethereum/go-ethereum/common"
17+
"github.com/ethereum/go-ethereum/core/types"
1718
"github.com/ethereum/go-ethereum/crypto"
1819
"github.com/ethereum/go-ethereum/ethclient"
1920
"github.com/pkg/errors"
@@ -24,10 +25,30 @@ import (
2425
"github.com/flare-foundation/go-flare-common/pkg/contracts/registry"
2526
)
2627

28+
const breakingEpochCoston2 = 5338
29+
30+
const (
31+
newRegistryCoston2Addr = "0x6a0AF07b7972177B176d3D422555cbc98DfDe914"
32+
oldRegistryCoston2Addr = "0xc6E40401395DCc648bC4bBb38fE4552423cD9BAC"
33+
34+
newPreRegistryCoston2Addr = "0xee963D1867d8B5f3D3E304802B40BC55B3eDeCB8"
35+
oldPreRegistryCoston2Addr = "0x47469Af25c253B4fb9b2a207BF4069574C6CcBd7"
36+
)
37+
2738
var (
28-
registratorArguments abi.Arguments
29-
registryAbi *abi.ABI
30-
preregistryAbi *abi.ABI
39+
newRegistryCoston2 = common.HexToAddress(newRegistryCoston2Addr)
40+
oldRegistryCoston2 = common.HexToAddress(oldRegistryCoston2Addr)
41+
42+
newPreRegistryCoston2 = common.HexToAddress(newPreRegistryCoston2Addr)
43+
oldPreRegistryCoston2 = common.HexToAddress(oldPreRegistryCoston2Addr)
44+
)
45+
46+
var (
47+
registratorArguments abi.Arguments
48+
registratorArgumentsNew abi.Arguments
49+
50+
registryAbi *abi.ABI
51+
preregistryAbi *abi.ABI
3152

3253
fallbackGasPrice = big.NewInt(50 * 1e9) // 50 GWei
3354
)
@@ -56,8 +77,27 @@ func init() {
5677
// panic, this error is fatal
5778
panic(err)
5879
}
80+
81+
uint256Ty, err := abi.NewType("uint256", "uint256", nil)
82+
if err != nil {
83+
// panic, this error is fatal
84+
panic(err)
85+
}
86+
5987
registratorArguments = abi.Arguments{
60-
{ // nextRewardEpochId
88+
{ // nextRewardEpochIDs
89+
Type: uint32Ty,
90+
},
91+
{ // address
92+
Type: addressTy,
93+
},
94+
}
95+
96+
registratorArgumentsNew = abi.Arguments{
97+
{ // chainID
98+
Type: uint256Ty,
99+
},
100+
{ // nextRewardEpochID
61101
Type: uint32Ty,
62102
},
63103
{ // address
@@ -84,14 +124,17 @@ type registryContractClient interface {
84124

85125
type registryContractClientImpl struct {
86126
ethClient *ethclient.Client
87-
address common.Address
127+
registryAddress common.Address
88128
preregistryAddress common.Address
89129
registry *registry.Registry
130+
oldRegistry *registry.Registry
90131
preregistry *preregistry.Preregistry
132+
oldPreregistry *preregistry.Preregistry
91133
senderTxOpts *bind.TransactOpts
92134
gasCfg *config.Gas
93135
txVerifier *chain.TxVerifier
94136
signerPrivateKey *ecdsa.PrivateKey
137+
chainID int
95138
}
96139

97140
func NewRegistryContractClient(
@@ -101,32 +144,53 @@ func NewRegistryContractClient(
101144
preregistryAddress common.Address,
102145
senderTxOpts *bind.TransactOpts,
103146
signerPk *ecdsa.PrivateKey,
147+
chainID int,
104148
) (*registryContractClientImpl, error) {
105-
registry, err := registry.NewRegistry(registryAddress, ethClient)
149+
registryBinding, err := registry.NewRegistry(registryAddress, ethClient)
106150
if err != nil {
107151
return nil, err
108152
}
109-
preregistry, err := preregistry.NewPreregistry(preregistryAddress, ethClient)
153+
preregistryBinding, err := preregistry.NewPreregistry(preregistryAddress, ethClient)
110154
if err != nil {
111155
return nil, err
112156
}
157+
158+
var oldRegistryBinding *registry.Registry
159+
if registryAddress == newRegistryCoston2 {
160+
oldRegistryBinding, err = registry.NewRegistry(oldRegistryCoston2, ethClient)
161+
if err != nil {
162+
return nil, err
163+
}
164+
}
165+
166+
var oldPreRegistryBinding *preregistry.Preregistry
167+
if preregistryAddress == newPreRegistryCoston2 {
168+
oldPreRegistryBinding, err = preregistry.NewPreregistry(oldPreRegistryCoston2, ethClient)
169+
if err != nil {
170+
return nil, err
171+
}
172+
}
173+
113174
return &registryContractClientImpl{
114175
ethClient: ethClient,
115-
address: registryAddress,
176+
registryAddress: registryAddress,
116177
preregistryAddress: preregistryAddress,
117-
registry: registry,
118-
preregistry: preregistry,
178+
registry: registryBinding,
179+
oldRegistry: oldRegistryBinding,
180+
preregistry: preregistryBinding,
181+
oldPreregistry: oldPreRegistryBinding,
119182
senderTxOpts: senderTxOpts,
120183
gasCfg: gasCfg,
121184
txVerifier: chain.NewTxVerifier(ethClient),
122185
signerPrivateKey: signerPk,
186+
chainID: chainID,
123187
}, nil
124188
}
125189

126190
// RegisterVoter tries to register voter on VoterRegistry smart contract.
127-
func (r *registryContractClientImpl) RegisterVoter(nextRewardEpochId *big.Int, address common.Address) <-chan shared.ExecuteStatus[any] {
191+
func (r *registryContractClientImpl) RegisterVoter(nextRewardEpochID *big.Int, address common.Address) <-chan shared.ExecuteStatus[any] {
128192
return shared.ExecuteWithRetryChan(func() (any, error) {
129-
err := r.sendRegisterVoter(nextRewardEpochId, address)
193+
err := r.sendRegisterVoter(nextRewardEpochID, address)
130194
if err != nil {
131195
if shared.ExistsAsSubstring(nonFatalRegisterErrors, err.Error()) {
132196
logger.Debugf("Non fatal error sending register voter: %v", err)
@@ -138,12 +202,29 @@ func (r *registryContractClientImpl) RegisterVoter(nextRewardEpochId *big.Int, a
138202
}, shared.MaxTxSendRetriesLong, shared.TxRetryIntervalLong)
139203
}
140204

141-
func (r *registryContractClientImpl) sendRegisterVoter(nextRewardEpochId *big.Int, address common.Address) error {
142-
epochId := uint32(nextRewardEpochId.Uint64())
143-
signature, err := r.createSignature(epochId, address)
144-
if err != nil {
145-
return err
205+
func (r *registryContractClientImpl) sendRegisterVoter(nextRewardEpochID *big.Int, address common.Address) error {
206+
epochID := uint32(nextRewardEpochID.Uint64())
207+
old, oldAddress := shouldUseOldRegistry(epochID, r.registryAddress)
208+
rAddress := r.registryAddress
209+
210+
var (
211+
signature []byte
212+
err error
213+
)
214+
215+
if old {
216+
rAddress = oldAddress
217+
signature, err = r.createSignatureOld(epochID, address)
218+
if err != nil {
219+
return fmt.Errorf("creating registry signature old: %w", err)
220+
}
221+
} else {
222+
signature, err = r.createSignatureNew(r.chainID, epochID, address)
223+
if err != nil {
224+
return fmt.Errorf("creating pre registry signature new: %w", err)
225+
}
146226
}
227+
147228
vrsSignature := registry.IVoterRegistrySignature{
148229
R: [32]byte(signature[0:32]),
149230
S: [32]byte(signature[32:64]),
@@ -159,7 +240,7 @@ func (r *registryContractClientImpl) sendRegisterVoter(nextRewardEpochId *big.In
159240
r.ethClient,
160241
chain.DefaultTxTimeout,
161242
r.senderTxOpts.From,
162-
r.address,
243+
rAddress,
163244
common.Big0,
164245
registryAbi,
165246
"registerVoter",
@@ -176,15 +257,25 @@ func (r *registryContractClientImpl) sendRegisterVoter(nextRewardEpochId *big.In
176257
r.senderTxOpts.GasLimit = estimatedGasLimit
177258
}
178259

179-
tx, err := r.registry.RegisterVoter(r.senderTxOpts, address, vrsSignature)
180-
if err != nil {
181-
return err
260+
var tx *types.Transaction
261+
262+
if old {
263+
tx, err = r.oldRegistry.RegisterVoter(r.senderTxOpts, address, vrsSignature)
264+
if err != nil {
265+
return fmt.Errorf("sending registry tx old: %w", err)
266+
}
267+
} else {
268+
tx, err = r.registry.RegisterVoter(r.senderTxOpts, address, vrsSignature)
269+
if err != nil {
270+
return fmt.Errorf("sending registry tx new: %w", err)
271+
}
182272
}
273+
183274
err = r.txVerifier.WaitUntilMined(r.senderTxOpts.From, tx, chain.DefaultTxTimeout)
184275
if err != nil {
185276
return err
186277
}
187-
logger.Infof("Voter %s registered for epoch %v", address, nextRewardEpochId)
278+
logger.Infof("Voter %s registered for epoch %v", address, nextRewardEpochID)
188279
return nil
189280
}
190281

@@ -203,12 +294,29 @@ func (r *registryContractClientImpl) PreregisterVoter(nextRewardEpochId *big.Int
203294
}, shared.MaxTxSendRetries, shared.TxRetryInterval)
204295
}
205296

206-
func (r *registryContractClientImpl) sendPreRegisterVoter(nextRewardEpochId *big.Int, address common.Address) error {
207-
epochId := uint32(nextRewardEpochId.Uint64())
208-
signature, err := r.createSignature(epochId, address)
209-
if err != nil {
210-
return err
297+
func (r *registryContractClientImpl) sendPreRegisterVoter(nextRewardEpochID *big.Int, address common.Address) error {
298+
epochID := uint32(nextRewardEpochID.Uint64())
299+
old, oldAddress := shouldUseOldPreRegistry(epochID, r.registryAddress)
300+
prAddress := r.preregistryAddress
301+
302+
var (
303+
signature []byte
304+
err error
305+
)
306+
307+
if old {
308+
prAddress = oldAddress
309+
signature, err = r.createSignatureOld(epochID, address)
310+
if err != nil {
311+
return fmt.Errorf("creating pre registry signature old: %w", err)
312+
}
313+
} else {
314+
signature, err = r.createSignatureNew(r.chainID, epochID, address)
315+
if err != nil {
316+
return fmt.Errorf("creating pre registry signature new: %w", err)
317+
}
211318
}
319+
212320
vrsSignature := preregistry.IVoterRegistrySignature{
213321
R: [32]byte(signature[0:32]),
214322
S: [32]byte(signature[32:64]),
@@ -217,14 +325,14 @@ func (r *registryContractClientImpl) sendPreRegisterVoter(nextRewardEpochId *big
217325

218326
err = SetGas(r.senderTxOpts, r.ethClient, r.gasCfg)
219327
if err != nil {
220-
return err
328+
return fmt.Errorf("setting gas pre registry:%w", err)
221329
}
222330

223331
estimatedGasLimit, err := chain.DryRunTxAbi(
224332
r.ethClient,
225333
chain.DefaultTxTimeout,
226334
r.senderTxOpts.From,
227-
r.preregistryAddress,
335+
prAddress,
228336
common.Big0,
229337
preregistryAbi,
230338
"preRegisterVoter",
@@ -241,21 +349,42 @@ func (r *registryContractClientImpl) sendPreRegisterVoter(nextRewardEpochId *big
241349
r.senderTxOpts.GasLimit = estimatedGasLimit
242350
}
243351

244-
tx, err := r.preregistry.PreRegisterVoter(r.senderTxOpts, address, vrsSignature)
245-
if err != nil {
246-
return err
352+
var tx *types.Transaction
353+
if old {
354+
tx, err = r.oldPreregistry.PreRegisterVoter(r.senderTxOpts, address, vrsSignature)
355+
if err != nil {
356+
return fmt.Errorf("sending preregistry tx old: %w", err)
357+
}
358+
} else {
359+
tx, err = r.preregistry.PreRegisterVoter(r.senderTxOpts, address, vrsSignature)
360+
if err != nil {
361+
return fmt.Errorf("sending preregistry tx new: %w", err)
362+
}
247363
}
364+
248365
err = r.txVerifier.WaitUntilMined(r.senderTxOpts.From, tx, chain.DefaultTxTimeout)
249366
if err != nil {
250367
return err
251368
}
252-
logger.Infof("Voter %s pre-registered for epoch %v", address, nextRewardEpochId)
369+
logger.Infof("Voter %s pre-registered for epoch %v", address, nextRewardEpochID)
253370
return nil
254371
}
255372

256-
// createSignature creates ECDSA message signature keccak256(abi.encode(nextRewardEpochId, address)) with signerPrivateKey
257-
func (r *registryContractClientImpl) createSignature(nextRewardEpochId uint32, address common.Address) ([]byte, error) {
258-
message, err := registratorArguments.Pack(nextRewardEpochId, address)
373+
// createSignatureOld creates ECDSA message signature keccak256(abi.encode(nextRewardEpochID, address)) with signerPrivateKey
374+
func (r *registryContractClientImpl) createSignatureOld(nextRewardEpochID uint32, address common.Address) ([]byte, error) {
375+
message, err := registratorArguments.Pack(nextRewardEpochID, address)
376+
if err != nil {
377+
return nil, err
378+
}
379+
messageHash := crypto.Keccak256(message)
380+
return crypto.Sign(accounts.TextHash(messageHash), r.signerPrivateKey)
381+
}
382+
383+
// createSignatureOld creates ECDSA message signature keccak256(abi.encode(chainID, nextRewardEpochID, address)) with signerPrivateKey
384+
func (r *registryContractClientImpl) createSignatureNew(chainID int, nextRewardEpochID uint32, address common.Address) ([]byte, error) {
385+
chainIDB := big.NewInt(int64(chainID))
386+
387+
message, err := registratorArgumentsNew.Pack(chainIDB, nextRewardEpochID, address)
259388
if err != nil {
260389
return nil, err
261390
}
@@ -311,3 +440,19 @@ func SetGas(txOptions *bind.TransactOpts, client *ethclient.Client, gasConfig *c
311440
return fmt.Errorf("unsupported tx type: %d", gasConfig.TxType)
312441
}
313442
}
443+
444+
func shouldUseOldRegistry(epochID uint32, address common.Address) (bool, common.Address) {
445+
if address == newRegistryCoston2 && epochID <= breakingEpochCoston2 {
446+
return true, oldRegistryCoston2
447+
}
448+
449+
return false, common.Address{}
450+
}
451+
452+
func shouldUseOldPreRegistry(epochID uint32, address common.Address) (bool, common.Address) {
453+
if address == newPreRegistryCoston2 && epochID <= breakingEpochCoston2 {
454+
return true, oldPreRegistryCoston2
455+
}
456+
457+
return false, common.Address{}
458+
}

0 commit comments

Comments
 (0)