Skip to content

Commit c9270cd

Browse files
Merge pull request #355 from datmedevil17/dev
feat: Introduce instruction to upgrade legacy nonce accounts.
2 parents 7926abb + da05bb9 commit c9270cd

3 files changed

Lines changed: 169 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2021 github.com/gagliardetto
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package system
16+
17+
import (
18+
"encoding/binary"
19+
"fmt"
20+
21+
ag_binary "github.com/gagliardetto/binary"
22+
ag_solanago "github.com/gagliardetto/solana-go"
23+
ag_format "github.com/gagliardetto/solana-go/text/format"
24+
ag_treeout "github.com/gagliardetto/treeout"
25+
)
26+
27+
// One-time idempotent upgrade of legacy nonce versions in order to bump
28+
// them out of chain blockhash domain.
29+
type UpgradeNonceAccount struct {
30+
31+
// [0] = [WRITE] NonceAccount
32+
// ··········· Nonce account
33+
ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"`
34+
}
35+
36+
// NewUpgradeNonceAccountInstructionBuilder creates a new `UpgradeNonceAccount` instruction builder.
37+
func NewUpgradeNonceAccountInstructionBuilder() *UpgradeNonceAccount {
38+
nd := &UpgradeNonceAccount{
39+
AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 1),
40+
}
41+
return nd
42+
}
43+
44+
// Nonce account
45+
func (inst *UpgradeNonceAccount) SetNonceAccount(nonceAccount ag_solanago.PublicKey) *UpgradeNonceAccount {
46+
inst.AccountMetaSlice[0] = ag_solanago.Meta(nonceAccount).WRITE()
47+
return inst
48+
}
49+
50+
func (inst *UpgradeNonceAccount) GetNonceAccount() *ag_solanago.AccountMeta {
51+
return inst.AccountMetaSlice[0]
52+
}
53+
54+
func (inst UpgradeNonceAccount) Build() *Instruction {
55+
return &Instruction{BaseVariant: ag_binary.BaseVariant{
56+
Impl: inst,
57+
TypeID: ag_binary.TypeIDFromUint32(Instruction_UpgradeNonceAccount, binary.LittleEndian),
58+
}}
59+
}
60+
61+
// ValidateAndBuild validates the instruction parameters and accounts;
62+
// if there is a validation error, it returns the error.
63+
// Otherwise, it builds and returns the instruction.
64+
func (inst UpgradeNonceAccount) ValidateAndBuild() (*Instruction, error) {
65+
if err := inst.Validate(); err != nil {
66+
return nil, err
67+
}
68+
return inst.Build(), nil
69+
}
70+
71+
func (inst *UpgradeNonceAccount) Validate() error {
72+
// Check whether all accounts are set:
73+
for accIndex, acc := range inst.AccountMetaSlice {
74+
if acc == nil {
75+
return fmt.Errorf("ins.AccountMetaSlice[%v] is not set", accIndex)
76+
}
77+
}
78+
return nil
79+
}
80+
81+
func (inst *UpgradeNonceAccount) EncodeToTree(parent ag_treeout.Branches) {
82+
parent.Child(ag_format.Program(ProgramName, ProgramID)).
83+
//
84+
ParentFunc(func(programBranch ag_treeout.Branches) {
85+
programBranch.Child(ag_format.Instruction("UpgradeNonceAccount")).
86+
//
87+
ParentFunc(func(instructionBranch ag_treeout.Branches) {
88+
89+
// Parameters of the instruction:
90+
instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {})
91+
92+
// Accounts of the instruction:
93+
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
94+
accountsBranch.Child(ag_format.Meta("Nonce", inst.AccountMetaSlice[0]))
95+
})
96+
})
97+
})
98+
}
99+
100+
func (inst UpgradeNonceAccount) MarshalWithEncoder(encoder *ag_binary.Encoder) error {
101+
return nil
102+
}
103+
104+
func (inst *UpgradeNonceAccount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error {
105+
return nil
106+
}
107+
108+
// NewUpgradeNonceAccountInstruction declares a new UpgradeNonceAccount instruction with the provided parameters and accounts.
109+
func NewUpgradeNonceAccountInstruction(
110+
// Accounts:
111+
nonceAccount ag_solanago.PublicKey) *UpgradeNonceAccount {
112+
return NewUpgradeNonceAccountInstructionBuilder().
113+
SetNonceAccount(nonceAccount)
114+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2021 github.com/gagliardetto
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package system
16+
17+
import (
18+
"bytes"
19+
"strconv"
20+
"testing"
21+
22+
ag_gofuzz "github.com/gagliardetto/gofuzz"
23+
ag_require "github.com/stretchr/testify/require"
24+
)
25+
26+
func TestEncodeDecode_UpgradeNonceAccount(t *testing.T) {
27+
fu := ag_gofuzz.New().NilChance(0)
28+
for i := 0; i < 1; i++ {
29+
t.Run("UpgradeNonceAccount"+strconv.Itoa(i), func(t *testing.T) {
30+
{
31+
params := new(UpgradeNonceAccount)
32+
fu.Fuzz(params)
33+
params.AccountMetaSlice = nil
34+
buf := new(bytes.Buffer)
35+
err := encodeT(*params, buf)
36+
ag_require.NoError(t, err)
37+
//
38+
got := new(UpgradeNonceAccount)
39+
err = decodeT(got, buf.Bytes())
40+
got.AccountMetaSlice = nil
41+
ag_require.NoError(t, err)
42+
ag_require.Equal(t, params, got)
43+
}
44+
})
45+
}
46+
}

programs/system/instructions.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ const (
7878

7979
// Transfer lamports from a derived address
8080
Instruction_TransferWithSeed
81+
82+
// One-time idempotent upgrade of legacy nonce versions in order to bump
83+
// them out of chain blockhash domain.
84+
Instruction_UpgradeNonceAccount
8185
)
8286

8387
// InstructionIDToName returns the name of the instruction given its ID.
@@ -107,6 +111,8 @@ func InstructionIDToName(id uint32) string {
107111
return "AssignWithSeed"
108112
case Instruction_TransferWithSeed:
109113
return "TransferWithSeed"
114+
case Instruction_UpgradeNonceAccount:
115+
return "UpgradeNonceAccount"
110116
default:
111117
return ""
112118
}
@@ -163,6 +169,9 @@ var InstructionImplDef = ag_binary.NewVariantDefinition(
163169
{
164170
"TransferWithSeed", (*TransferWithSeed)(nil),
165171
},
172+
{
173+
"UpgradeNonceAccount", (*UpgradeNonceAccount)(nil),
174+
},
166175
},
167176
)
168177

0 commit comments

Comments
 (0)