Skip to content

Commit 031adfb

Browse files
[DPA-1519]: feat(solana): allow override authority on Configurer (#329)
When executing SetConfig via MCMS, the authority has to be the timelock signer, the current implementation does not allow any override and only accepts the `auth` or deploykey as the authority. JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1519
1 parent 5089c48 commit 031adfb

File tree

3 files changed

+63
-18
lines changed

3 files changed

+63
-18
lines changed

.changeset/wise-gorillas-care.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@smartcontractkit/mcms": minor
3+
---
4+
5+
feat(solana): override authority on Configurer

sdk/solana/configurer.go

+25-13
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,32 @@ var _ sdk.Configurer = &Configurer{}
2121
// Configurer configures the MCM contract for Solana chains.
2222
type Configurer struct {
2323
instructionCollection
24-
chainSelector types.ChainSelector
25-
client *rpc.Client
26-
auth solana.PrivateKey
27-
skipSend bool
24+
chainSelector types.ChainSelector
25+
client *rpc.Client
26+
auth solana.PrivateKey
27+
skipSend bool
28+
authorityAccount solana.PublicKey
2829
}
2930

3031
// NewConfigurer creates a new Configurer for Solana chains.
3132
//
3233
// options:
3334
//
3435
// WithDoNotSendInstructionsOnChain: when selected, the Configurer instance will not
35-
// send the Solana instructions to the blockchain.
36+
// send the Solana instructions to the blockchain.
37+
//
38+
// WithAuthorityAccount: sets the authorityAccount for the MCM contract. Defaults to the `auth` field if unset.
39+
// Main use case is to allow authorityAccount to be overridden when processing the SetConfig with MCMS where
40+
// the authorityAccount has to be the timelock signer.
3641
func NewConfigurer(
3742
client *rpc.Client, auth solana.PrivateKey, chainSelector types.ChainSelector, options ...configurerOption,
3843
) *Configurer {
3944
configurer := &Configurer{
40-
client: client,
41-
auth: auth,
42-
chainSelector: chainSelector,
43-
skipSend: false,
45+
client: client,
46+
auth: auth,
47+
chainSelector: chainSelector,
48+
skipSend: false,
49+
authorityAccount: auth.PublicKey(),
4450
}
4551
for _, opt := range options {
4652
opt(configurer)
@@ -57,6 +63,12 @@ func WithDoNotSendInstructionsOnChain() configurerOption {
5763
}
5864
}
5965

66+
func WithAuthorityAccount(authorityAccount solana.PublicKey) configurerOption {
67+
return func(c *Configurer) {
68+
c.authorityAccount = authorityAccount
69+
}
70+
}
71+
6072
// SetConfig sets the configuration for the MCM contract on the Solana chain.
6173
//
6274
// The list of instructions needed to set the configuration is returned in the
@@ -120,7 +132,7 @@ func (c *Configurer) SetConfig(
120132
configSignersPDA,
121133
rootMetadataPDA,
122134
expiringRootAndOpCountPDA,
123-
c.auth.PublicKey(),
135+
c.authorityAccount,
124136
solana.SystemProgramID))
125137
if err != nil {
126138
return types.TransactionResult{}, err
@@ -148,21 +160,21 @@ func (c *Configurer) preloadSigners(
148160
configSignersPDA solana.PublicKey,
149161
) error {
150162
err := c.addInstruction("initSigners", bindings.NewInitSignersInstruction(mcmName, uint8(len(signerAddresses)), //nolint:gosec
151-
configPDA, configSignersPDA, c.auth.PublicKey(), solana.SystemProgramID))
163+
configPDA, configSignersPDA, c.authorityAccount, solana.SystemProgramID))
152164
if err != nil {
153165
return err
154166
}
155167

156168
for i, chunkIndex := range chunkIndexes(len(signerAddresses), config.MaxAppendSignerBatchSize) {
157169
err = c.addInstruction(fmt.Sprintf("appendSigners%d", i), bindings.NewAppendSignersInstruction(mcmName,
158-
signerAddresses[chunkIndex[0]:chunkIndex[1]], configPDA, configSignersPDA, c.auth.PublicKey()))
170+
signerAddresses[chunkIndex[0]:chunkIndex[1]], configPDA, configSignersPDA, c.authorityAccount))
159171
if err != nil {
160172
return err
161173
}
162174
}
163175

164176
err = c.addInstruction("finalizeSigners", bindings.NewFinalizeSignersInstruction(mcmName, configPDA,
165-
configSignersPDA, c.auth.PublicKey()))
177+
configSignersPDA, c.authorityAccount))
166178
if err != nil {
167179
return err
168180
}

sdk/solana/configurer_test.go

+33-5
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,36 @@ func Test_NewConfigurer(t *testing.T) {
2626
auth := solana.MustPrivateKeyFromBase58("DmPfeHBC8Brf8s5qQXi25bmJ996v6BHRtaLc6AH51yFGSqQpUMy1oHkbbXobPNBdgGH2F29PAmoq9ZZua4K9vCc")
2727
chainSelector := types.ChainSelector(cselectors.SOLANA_DEVNET.Selector)
2828

29+
newAuthorityAccount := solana.NewWallet().PublicKey()
30+
2931
tests := []struct {
30-
name string
31-
constructorFn func() *Configurer
32-
wantSkipTransaction bool
32+
name string
33+
constructorFn func() *Configurer
34+
wantSkipTransaction bool
35+
wantAuthorityAccount solana.PublicKey
3336
}{
3437
{
3538
name: "standard args",
3639
constructorFn: func() *Configurer {
3740
return NewConfigurer(client, auth, chainSelector)
3841
},
39-
wantSkipTransaction: false,
42+
wantSkipTransaction: false,
43+
wantAuthorityAccount: auth.PublicKey(),
4044
},
4145
{
4246
name: "skip transaction option",
4347
constructorFn: func() *Configurer {
4448
return NewConfigurer(client, auth, chainSelector, WithDoNotSendInstructionsOnChain())
4549
},
46-
wantSkipTransaction: true,
50+
wantSkipTransaction: true,
51+
wantAuthorityAccount: auth.PublicKey(),
52+
},
53+
{
54+
name: "override authorityAccount",
55+
constructorFn: func() *Configurer {
56+
return NewConfigurer(client, auth, chainSelector, WithAuthorityAccount(newAuthorityAccount))
57+
},
58+
wantAuthorityAccount: newAuthorityAccount,
4759
},
4860
}
4961

@@ -54,6 +66,7 @@ func Test_NewConfigurer(t *testing.T) {
5466

5567
require.NotNil(t, configurer)
5668
require.Equal(t, tt.wantSkipTransaction, configurer.skipSend)
69+
require.Equal(t, tt.wantAuthorityAccount, configurer.authorityAccount)
5770
})
5871
}
5972
}
@@ -67,6 +80,7 @@ func TestConfigurer_SetConfig(t *testing.T) {
6780
require.NoError(t, err)
6881
defaultMcmConfig := &types.Config{Quorum: 1, Signers: []common.Address{common.HexToAddress("0x1")}}
6982
clearRoot := false
83+
newAuthorityAccount := solana.NewWallet().PublicKey()
7084

7185
tests := []struct {
7286
name string
@@ -118,6 +132,20 @@ func TestConfigurer_SetConfig(t *testing.T) {
118132
bindings.NewSetConfigInstructionBuilder().Build(),
119133
},
120134
},
135+
{
136+
name: "success - override authorityAccount acciybt",
137+
auth: auth,
138+
options: []configurerOption{WithDoNotSendInstructionsOnChain(), WithAuthorityAccount(newAuthorityAccount)},
139+
mcmConfig: defaultMcmConfig,
140+
setup: func(t *testing.T, configurer *Configurer, mockJSONRPCClient *mocks.JSONRPCClient) { t.Helper() },
141+
wantHash: "",
142+
wantInstructions: []solana.Instruction{
143+
bindings.NewInitSignersInstructionBuilder().Build(),
144+
bindings.NewAppendSignersInstructionBuilder().Build(),
145+
bindings.NewFinalizeSignersInstructionBuilder().Build(),
146+
bindings.NewSetConfigInstructionBuilder().Build(),
147+
},
148+
},
121149
{
122150
name: "failure: too many signers",
123151
auth: auth,

0 commit comments

Comments
 (0)