2021-10-07 10:54:11 -07:00
|
|
|
// Copyright 2021 github.com/gagliardetto
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Create new accounts, allocate account data, assign accounts to owning programs,
|
|
|
|
// transfer lamports from System Program owned accounts and pay transacation fees.
|
2020-11-09 10:09:50 -08:00
|
|
|
|
2020-08-14 15:29:24 -07:00
|
|
|
package system
|
|
|
|
|
|
|
|
import (
|
2020-11-24 11:39:33 -08:00
|
|
|
"bytes"
|
2020-11-26 09:51:11 -08:00
|
|
|
"encoding/binary"
|
2020-11-18 05:39:50 -08:00
|
|
|
"fmt"
|
2021-09-01 03:55:18 -07:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
ag_spew "github.com/davecgh/go-spew/spew"
|
2021-09-04 05:03:55 -07:00
|
|
|
ag_binary "github.com/gagliardetto/binary"
|
2021-08-31 07:27:21 -07:00
|
|
|
ag_solanago "github.com/gagliardetto/solana-go"
|
|
|
|
ag_text "github.com/gagliardetto/solana-go/text"
|
|
|
|
ag_treeout "github.com/gagliardetto/treeout"
|
2020-08-14 15:29:24 -07:00
|
|
|
)
|
|
|
|
|
2021-09-01 03:55:18 -07:00
|
|
|
var ProgramID ag_solanago.PublicKey = ag_solanago.SystemProgramID
|
2021-08-31 07:27:21 -07:00
|
|
|
|
|
|
|
func SetProgramID(pubkey ag_solanago.PublicKey) {
|
|
|
|
ProgramID = pubkey
|
|
|
|
ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction)
|
|
|
|
}
|
2021-08-11 09:21:35 -07:00
|
|
|
|
|
|
|
const ProgramName = "System"
|
2020-11-18 05:39:50 -08:00
|
|
|
|
|
|
|
func init() {
|
2021-09-01 03:55:18 -07:00
|
|
|
ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction)
|
2020-11-18 05:39:50 -08:00
|
|
|
}
|
|
|
|
|
2021-07-29 08:19:13 -07:00
|
|
|
const (
|
2021-08-31 07:27:21 -07:00
|
|
|
// Create a new account
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_CreateAccount uint32 = iota
|
2020-11-18 05:39:50 -08:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Assign account to a program
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_Assign
|
2020-11-18 05:39:50 -08:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Transfer lamports
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_Transfer
|
2020-11-18 05:39:50 -08:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Create a new account at an address derived from a base pubkey and a seed
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_CreateAccountWithSeed
|
2020-11-18 05:39:50 -08:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Consumes a stored nonce, replacing it with a successor
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_AdvanceNonceAccount
|
2020-11-26 14:05:05 -08:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Withdraw funds from a nonce account
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_WithdrawNonceAccount
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Drive state of Uninitalized nonce account to Initialized, setting the nonce value
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_InitializeNonceAccount
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Change the entity authorized to execute nonce instructions on the account
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_AuthorizeNonceAccount
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Allocate space in a (possibly new) account without funding
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_Allocate
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Allocate space for and assign an account at an address derived from a base public key and a seed
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_AllocateWithSeed
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Assign account to a program based on a seed
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_AssignWithSeed
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// Transfer lamports from a derived address
|
2021-07-29 08:19:13 -07:00
|
|
|
Instruction_TransferWithSeed
|
|
|
|
)
|
2021-07-27 12:10:13 -07:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
// InstructionIDToName returns the name of the instruction given its ID.
|
2021-08-11 09:21:35 -07:00
|
|
|
func InstructionIDToName(id uint32) string {
|
|
|
|
switch id {
|
|
|
|
case Instruction_CreateAccount:
|
|
|
|
return "CreateAccount"
|
|
|
|
case Instruction_Assign:
|
|
|
|
return "Assign"
|
|
|
|
case Instruction_Transfer:
|
|
|
|
return "Transfer"
|
|
|
|
case Instruction_CreateAccountWithSeed:
|
|
|
|
return "CreateAccountWithSeed"
|
|
|
|
case Instruction_AdvanceNonceAccount:
|
|
|
|
return "AdvanceNonceAccount"
|
|
|
|
case Instruction_WithdrawNonceAccount:
|
|
|
|
return "WithdrawNonceAccount"
|
|
|
|
case Instruction_InitializeNonceAccount:
|
|
|
|
return "InitializeNonceAccount"
|
|
|
|
case Instruction_AuthorizeNonceAccount:
|
|
|
|
return "AuthorizeNonceAccount"
|
|
|
|
case Instruction_Allocate:
|
|
|
|
return "Allocate"
|
|
|
|
case Instruction_AllocateWithSeed:
|
|
|
|
return "AllocateWithSeed"
|
|
|
|
case Instruction_AssignWithSeed:
|
|
|
|
return "AssignWithSeed"
|
|
|
|
case Instruction_TransferWithSeed:
|
|
|
|
return "TransferWithSeed"
|
|
|
|
default:
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-18 13:45:59 -08:00
|
|
|
type Instruction struct {
|
2021-08-31 07:27:21 -07:00
|
|
|
ag_binary.BaseVariant
|
2020-08-14 15:29:24 -07:00
|
|
|
}
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) {
|
|
|
|
if enToTree, ok := inst.Impl.(ag_text.EncodableToTree); ok {
|
|
|
|
enToTree.EncodeToTree(parent)
|
|
|
|
} else {
|
|
|
|
parent.Child(ag_spew.Sdump(inst))
|
|
|
|
}
|
|
|
|
}
|
2021-07-29 08:58:03 -07:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
var InstructionImplDef = ag_binary.NewVariantDefinition(
|
|
|
|
ag_binary.Uint32TypeIDEncoding,
|
|
|
|
[]ag_binary.VariantType{
|
|
|
|
{
|
|
|
|
"CreateAccount", (*CreateAccount)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Assign", (*Assign)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Transfer", (*Transfer)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"CreateAccountWithSeed", (*CreateAccountWithSeed)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"AdvanceNonceAccount", (*AdvanceNonceAccount)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WithdrawNonceAccount", (*WithdrawNonceAccount)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"InitializeNonceAccount", (*InitializeNonceAccount)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"AuthorizeNonceAccount", (*AuthorizeNonceAccount)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Allocate", (*Allocate)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"AllocateWithSeed", (*AllocateWithSeed)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"AssignWithSeed", (*AssignWithSeed)(nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"TransferWithSeed", (*TransferWithSeed)(nil),
|
|
|
|
},
|
|
|
|
},
|
2021-07-29 08:19:13 -07:00
|
|
|
)
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func (inst *Instruction) ProgramID() ag_solanago.PublicKey {
|
|
|
|
return ProgramID
|
2020-11-26 14:05:05 -08:00
|
|
|
}
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func (inst *Instruction) Accounts() (out []*ag_solanago.AccountMeta) {
|
|
|
|
return inst.Impl.(ag_solanago.AccountsGettable).GetAccounts()
|
2020-11-26 14:05:05 -08:00
|
|
|
}
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func (inst *Instruction) Data() ([]byte, error) {
|
2020-11-26 14:05:05 -08:00
|
|
|
buf := new(bytes.Buffer)
|
2021-08-31 07:27:21 -07:00
|
|
|
if err := ag_binary.NewBinEncoder(buf).Encode(inst); err != nil {
|
2020-11-26 14:05:05 -08:00
|
|
|
return nil, fmt.Errorf("unable to encode instruction: %w", err)
|
|
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func (inst *Instruction) TextEncode(encoder *ag_text.Encoder, option *ag_text.Option) error {
|
|
|
|
return encoder.Encode(inst.Impl, option)
|
2020-11-18 13:45:59 -08:00
|
|
|
}
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error {
|
|
|
|
return inst.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef)
|
2020-11-09 07:02:28 -08:00
|
|
|
}
|
2020-11-06 11:43:44 -08:00
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func (inst *Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error {
|
|
|
|
err := encoder.WriteUint32(inst.TypeID.Uint32(), binary.LittleEndian)
|
2020-11-26 09:51:11 -08:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to write variant type: %w", err)
|
|
|
|
}
|
2021-08-31 07:27:21 -07:00
|
|
|
return encoder.Encode(inst.Impl)
|
2020-11-26 09:51:11 -08:00
|
|
|
}
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func registryDecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (interface{}, error) {
|
2021-07-29 08:19:13 -07:00
|
|
|
inst, err := DecodeInstruction(accounts, data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-11-20 11:24:07 -08:00
|
|
|
}
|
2021-07-29 08:19:13 -07:00
|
|
|
return inst, nil
|
2020-11-20 11:24:07 -08:00
|
|
|
}
|
|
|
|
|
2021-08-31 07:27:21 -07:00
|
|
|
func DecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (*Instruction, error) {
|
|
|
|
inst := new(Instruction)
|
|
|
|
if err := ag_binary.NewBinDecoder(data).Decode(inst); err != nil {
|
2021-08-08 08:51:50 -07:00
|
|
|
return nil, fmt.Errorf("unable to decode instruction: %w", err)
|
2020-11-20 11:24:07 -08:00
|
|
|
}
|
2021-08-31 07:27:21 -07:00
|
|
|
if v, ok := inst.Impl.(ag_solanago.AccountsSettable); ok {
|
2021-07-29 08:19:13 -07:00
|
|
|
err := v.SetAccounts(accounts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to set accounts for instruction: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return inst, nil
|
2020-08-14 15:29:24 -07:00
|
|
|
}
|