-
Notifications
You must be signed in to change notification settings - Fork 205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
En 12302 cosigned set guardian #4119
Changes from all commits
d659ab9
bc49f73
aafd07b
7be565e
3d6e4f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package guardian | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"sync" | ||
|
||
|
@@ -15,29 +16,34 @@ import ( | |
|
||
var guardianKey = []byte(core.ElrondProtectedKeyPrefix + core.GuardiansKeyIdentifier) | ||
|
||
const epochsForActivation = 10 // TODO: take from config | ||
|
||
type guardedAccount struct { | ||
marshaller marshal.Marshalizer | ||
epochNotifier vmcommon.EpochNotifier | ||
mutEpoch sync.RWMutex | ||
currentEpoch uint32 | ||
guardianActivationEpochs uint32 | ||
marshaller marshal.Marshalizer | ||
epochNotifier vmcommon.EpochNotifier | ||
mutEpoch sync.RWMutex | ||
guardianActivationEpochsDelay uint32 | ||
currentEpoch uint32 | ||
} | ||
|
||
// NewGuardedAccount creates a new guarded account | ||
func NewGuardedAccount(marshaller marshal.Marshalizer, epochNotifier vmcommon.EpochNotifier) (*guardedAccount, error) { | ||
func NewGuardedAccount( | ||
marshaller marshal.Marshalizer, | ||
epochNotifier vmcommon.EpochNotifier, | ||
setGuardianEpochsDelay uint32, | ||
) (*guardedAccount, error) { | ||
if check.IfNil(marshaller) { | ||
return nil, process.ErrNilMarshalizer | ||
} | ||
if check.IfNil(epochNotifier) { | ||
return nil, process.ErrNilEpochNotifier | ||
} | ||
if setGuardianEpochsDelay == 0 { | ||
raduchis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return nil, process.ErrInvalidSetGuardianEpochsDelay | ||
} | ||
|
||
agc := &guardedAccount{ | ||
marshaller: marshaller, | ||
epochNotifier: epochNotifier, | ||
guardianActivationEpochs: epochsForActivation, | ||
marshaller: marshaller, | ||
epochNotifier: epochNotifier, | ||
guardianActivationEpochsDelay: setGuardianEpochsDelay, | ||
} | ||
|
||
epochNotifier.RegisterNotifyHandler(agc) | ||
|
@@ -69,17 +75,21 @@ func (agc *guardedAccount) GetActiveGuardian(uah vmcommon.UserAccountHandler) ([ | |
} | ||
|
||
// SetGuardian sets a guardian for an account | ||
func (agc *guardedAccount) SetGuardian(uah vmcommon.UserAccountHandler, guardianAddress []byte) error { | ||
guardian := &guardians.Guardian{ | ||
Address: guardianAddress, | ||
ActivationEpoch: agc.currentEpoch + agc.guardianActivationEpochs, | ||
} | ||
|
||
func (agc *guardedAccount) SetGuardian(uah vmcommon.UserAccountHandler, guardianAddress []byte, txGuardianAddress []byte) error { | ||
stateUserAccount, ok := uah.(state.UserAccountHandler) | ||
if !ok { | ||
return process.ErrWrongTypeAssertion | ||
} | ||
|
||
if len(txGuardianAddress) > 0 { | ||
return agc.instantSetGuardian(stateUserAccount, guardianAddress, txGuardianAddress) | ||
} | ||
|
||
guardian := &guardians.Guardian{ | ||
Address: guardianAddress, | ||
raduchis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ActivationEpoch: agc.currentEpoch + agc.guardianActivationEpochsDelay, | ||
} | ||
|
||
return agc.setAccountGuardian(stateUserAccount, guardian) | ||
} | ||
|
||
|
@@ -88,6 +98,7 @@ func (agc *guardedAccount) setAccountGuardian(uah state.UserAccountHandler, guar | |
if err != nil { | ||
return err | ||
} | ||
|
||
newGuardians, err := agc.updateGuardians(guardian, configuredGuardians) | ||
if err != nil { | ||
return err | ||
|
@@ -101,6 +112,43 @@ func (agc *guardedAccount) setAccountGuardian(uah state.UserAccountHandler, guar | |
return agc.saveAccountGuardians(accHandler, newGuardians) | ||
} | ||
|
||
func (agc *guardedAccount) instantSetGuardian( | ||
uah state.UserAccountHandler, | ||
guardianAddress []byte, | ||
txGuardianAddress []byte, | ||
) error { | ||
accountGuardians, err := agc.getConfiguredGuardians(uah) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
activeGuardian, err := agc.getActiveGuardian(accountGuardians) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if !bytes.Equal(activeGuardian.Address, txGuardianAddress) { | ||
return process.ErrTransactionAndAccountGuardianMismatch | ||
} | ||
|
||
// immediately set the new guardian | ||
guardian := &guardians.Guardian{ | ||
Address: guardianAddress, | ||
ActivationEpoch: agc.currentEpoch, | ||
} | ||
|
||
accountGuardians.Slice = []*guardians.Guardian{guardian} | ||
accHandler, ok := uah.(vmcommon.UserAccountHandler) | ||
if !ok { | ||
return process.ErrWrongTypeAssertion | ||
} | ||
|
||
return agc.saveAccountGuardians(accHandler, accountGuardians) | ||
} | ||
|
||
// TODO: add constraints on not co-signed txs on interceptor, for setGuardian | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. task for TODO? Also, question: is there a check as to not send value on a setGuardian transaction call? (in builtin function implementation) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Created a task: [EN-12365] for the TODO.
The check is already done on checkBaseAccountFreezerArgs for all related builtin functions if !isZero(vmInput.CallValue) {
return ErrBuiltInFunctionCalledWithValue
} |
||
// 1. Gas price cannot exceed a preconfigured limit | ||
// 2. If there is already one guardian pending, do not allow setting another one | ||
func (agc *guardedAccount) updateGuardians(newGuardian *guardians.Guardian, accountGuardians *guardians.Guardians) (*guardians.Guardians, error) { | ||
numSetGuardians := len(accountGuardians.Slice) | ||
|
||
|
@@ -115,7 +163,7 @@ func (agc *guardedAccount) updateGuardians(newGuardian *guardians.Guardian, acco | |
return nil, fmt.Errorf("%w in updateGuardians, with %d configured guardians", err, numSetGuardians) | ||
} | ||
|
||
if activeGuardian.Equal(newGuardian) { | ||
if bytes.Equal(activeGuardian.Address, newGuardian.Address) { | ||
accountGuardians.Slice = []*guardians.Guardian{activeGuardian} | ||
} else { | ||
accountGuardians.Slice = []*guardians.Guardian{activeGuardian, newGuardian} | ||
|
@@ -175,7 +223,7 @@ func (agc *guardedAccount) getActiveGuardian(gs *guardians.Guardians) (*guardian | |
} | ||
|
||
if selectedGuardian == nil { | ||
return nil, process.ErrActiveHasNoActiveGuardian | ||
return nil, process.ErrAccountHasNoActiveGuardian | ||
} | ||
|
||
return selectedGuardian, nil | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove extra line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done on #4159