Skip to content

Commit

Permalink
Fix missing key checks
Browse files Browse the repository at this point in the history
  • Loading branch information
gagliardetto committed Nov 3, 2024
1 parent 218180d commit 29f1ed1
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 45 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ require (
github.com/spf13/cast v1.3.0 // indirect
github.com/spf13/jwalterweatherman v1.0.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
Expand Down
12 changes: 0 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -309,25 +309,18 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE=
github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE=
go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
go.mongodb.org/mongo-driver v1.12.2 h1:gbWY1bJkkmUB9jjZzcdhOL8O85N9H+Vvsf2yFN0RDws=
go.mongodb.org/mongo-driver v1.12.2/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
Expand Down Expand Up @@ -415,7 +408,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
Expand Down Expand Up @@ -467,14 +459,11 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -483,7 +472,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
Expand Down
67 changes: 55 additions & 12 deletions keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ import (

type PrivateKey []byte

// IsValid returns whether the private key is valid.
func (k PrivateKey) IsValid() bool {
_, err := ValidatePrivateKey(k)
return err == nil
}

func (k PrivateKey) Validate() error {
_, err := ValidatePrivateKey(k)
return err
}

func MustPrivateKeyFromBase58(in string) PrivateKey {
out, err := PrivateKeyFromBase58(in)
if err != nil {
Expand All @@ -50,22 +61,41 @@ func PrivateKeyFromBase58(privkey string) (PrivateKey, error) {
if err != nil {
return nil, err
}
// validate
if _, err := ValidatePrivateKey(res); err != nil {
return nil, err
}
return res, nil
}

func ValidatePrivateKey(b []byte) (bool, error) {
if len(b) != ed25519.PrivateKeySize {
return false, fmt.Errorf("invalid private key size, expected %v, got %d", ed25519.PrivateKeySize, len(b))
}
// check if the public key is on the ed25519 curve
pub := ed25519.PrivateKey(b).Public().(ed25519.PublicKey)
if !IsOnCurve(pub) {
return false, errors.New("the corresponding public key is not on the ed25519 curve")
}
return true, nil
}

func PrivateKeyFromSolanaKeygenFile(file string) (PrivateKey, error) {
content, err := ioutil.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("read keygen file: %w", err)
}

var values []byte
err = json.Unmarshal(content, &values)
var privateKeyBytes []byte
err = json.Unmarshal(content, &privateKeyBytes)
if err != nil {
return nil, fmt.Errorf("decode keygen file: %w", err)
}

return PrivateKey([]byte(values)), nil
if _, err := ValidatePrivateKey(privateKeyBytes); err != nil {
return nil, fmt.Errorf("invalid private key: %w", err)
}
return PrivateKey(privateKeyBytes), nil
}

func (k PrivateKey) String() string {
Expand All @@ -83,6 +113,9 @@ func NewRandomPrivateKey() (PrivateKey, error) {
}

func (k PrivateKey) Sign(payload []byte) (Signature, error) {
if err := k.Validate(); err != nil {
return Signature{}, err
}
p := ed25519.PrivateKey(k)
signData, err := p.Sign(crypto_rand.Reader, payload, crypto.Hash(0))
if err != nil {
Expand All @@ -96,6 +129,10 @@ func (k PrivateKey) Sign(payload []byte) (Signature, error) {
}

func (k PrivateKey) PublicKey() PublicKey {
if err := k.Validate(); err != nil {
panic(err)
}

p := ed25519.PrivateKey(k)
pub := p.Public().(ed25519.PublicKey)

Expand All @@ -115,18 +152,16 @@ func (p PublicKey) Verify(message []byte, signature Signature) bool {

type PublicKey [PublicKeyLength]byte

// PublicKeyFromBytes creates a PublicKey from a byte slice that must be 32 bytes long.
// NOTE: it will accept on- and off-curve pubkeys.
func PublicKeyFromBytes(in []byte) (out PublicKey) {
byteCount := len(in)
if byteCount == 0 {
return
}

max := PublicKeyLength
if byteCount < max {
max = byteCount
if byteCount != PublicKeyLength {
panic(fmt.Errorf("invalid public key size, expected %v, got %d", PublicKeyLength, byteCount))
}

copy(out[:], in[0:max])
copy(out[:], in)
return
}

Expand All @@ -143,6 +178,8 @@ func MustPublicKeyFromBase58(in string) PublicKey {
return out
}

// PublicKeyFromBase58 creates a PublicKey from a base58 encoded string.
// NOTE: it will accept on- and off-curve pubkeys.
func PublicKeyFromBase58(in string) (out PublicKey, err error) {
val, err := base58.Decode(in)
if err != nil {
Expand Down Expand Up @@ -551,15 +588,18 @@ func isNativeProgramID(key PublicKey) bool {
}

const (
/// Number of bytes in a pubkey.
// Number of bytes in a pubkey.
PublicKeyLength = 32
// Maximum length of derived pubkey seed.
MaxSeedLength = 32
// Maximum number of seeds.
MaxSeeds = 16
/// Number of bytes in a signature.
// Number of bytes in a signature.
SignatureLength = 64

// Number of bytes in a private key.
PrivateKeyLength = ed25519.PrivateKeySize

// // Maximum string length of a base58 encoded pubkey.
// MaxBase58Length = 44
)
Expand Down Expand Up @@ -621,6 +661,9 @@ func CreateProgramAddress(seeds [][]byte, programID PublicKey) (PublicKey, error

// Check if the provided `b` is on the ed25519 curve.
func IsOnCurve(b []byte) bool {
if len(b) != ed25519.PublicKeySize {
return false
}
_, err := new(edwards25519.Point).SetBytes(b)
isOnCurve := err == nil
return isOnCurve
Expand Down
22 changes: 22 additions & 0 deletions nativetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,28 @@ func (p Signature) String() string {
return base58.Encode(p[:])
}

type Base64 []byte

func (t Base64) MarshalJSON() ([]byte, error) {
return json.Marshal(base64.StdEncoding.EncodeToString(t))
}

func (t *Base64) UnmarshalJSON(data []byte) (err error) {
var s string
err = json.Unmarshal(data, &s)
if err != nil {
return
}

if s == "" {
*t = []byte{}
return nil
}

*t, err = base64.StdEncoding.DecodeString(s)
return
}

type Base58 []byte

func (t Base58) MarshalJSON() ([]byte, error) {
Expand Down
9 changes: 5 additions & 4 deletions rpc/getBlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ type GetBlockOpts struct {
MaxSupportedTransactionVersion *uint64
}

var (
MaxSupportedTransactionVersion0 uint64 = 0
MaxSupportedTransactionVersion1 uint64 = 1
)

// GetBlock returns identity and transaction information about a confirmed block in the ledger.
func (cl *Client) GetBlock(
ctx context.Context,
Expand All @@ -84,7 +89,6 @@ func (cl *Client) GetBlockWithOpts(
slot uint64,
opts *GetBlockOpts,
) (out *GetBlockResult, err error) {

obj := M{
"encoding": solana.EncodingBase64,
}
Expand Down Expand Up @@ -121,7 +125,6 @@ func (cl *Client) GetBlockWithOpts(
params := []interface{}{slot, obj}

err = cl.rpcClient.CallForInto(ctx, &out, "getBlock", params)

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -167,7 +170,6 @@ func (cl *Client) GetParsedBlockWithOpts(
slot uint64,
opts *GetBlockOpts,
) (out *GetParsedBlockResult, err error) {

obj := M{
"encoding": solana.EncodingJSONParsed,
}
Expand All @@ -190,7 +192,6 @@ func (cl *Client) GetParsedBlockWithOpts(
params := []interface{}{slot, obj}

err = cl.rpcClient.CallForInto(ctx, &out, "getBlock", params)

if err != nil {
return nil, err
}
Expand Down
19 changes: 9 additions & 10 deletions rpc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,24 +216,23 @@ type TransactionMeta struct {

LoadedAddresses LoadedAddresses `json:"loadedAddresses"`

ReturnData ReturnData `json:"returnData"`

ComputeUnitsConsumed *uint64 `json:"computeUnitsConsumed"`
}

type ReturnData struct {
ProgramId solana.PublicKey `json:"programId"`
Data solana.Data `json:"data"`
}

type InnerInstruction struct {
// TODO: <number> == int64 ???
// Index of the transaction instruction from which the inner instruction(s) originated
Index uint16 `json:"index"`

// Ordered list of inner program instructions that were invoked during a single transaction instruction.
Instructions []CompiledInnerInstruction `json:"instructions"`
}

type CompiledInnerInstruction struct {
solana.CompiledInstruction

// Invocation stack height of this instruction. Instruction stack height
// starts at 1 for transaction instructions.
StackHeight uint8 `json:"stackHeight"`
Instructions []solana.CompiledInstruction `json:"instructions"`
}

// Ok interface{} `json:"Ok"` // <null> Transaction was successful
Expand Down Expand Up @@ -511,7 +510,7 @@ type ParsedInstruction struct {
Parsed *InstructionInfoEnvelope `json:"parsed,omitempty"`
Data solana.Base58 `json:"data,omitempty"`
Accounts []solana.PublicKey `json:"accounts,omitempty"`
StackHeight int `json:"stackHeight"`
StackHeight int64 `json:"stackHeight"`
}

type InstructionInfoEnvelope struct {
Expand Down
8 changes: 2 additions & 6 deletions transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ type CompiledInstruction struct {
Data Base58 `json:"data"`

//
StackHeight int `json:"stackHeight"`
StackHeight int64 `json:"stackHeight"`
}

type compiledInstruction struct {
Expand All @@ -159,11 +159,7 @@ type compiledInstruction struct {
Data Base58 `json:"data"`

//
StackHeight int `json:"stackHeight"`
}

func (ci *CompiledInstruction) MarshalJSON() ([]byte, error) {
return json.Marshal(ci)
StackHeight int64 `json:"stackHeight"`
}

func (ci *CompiledInstruction) UnmarshalJSON(data []byte) error {
Expand Down

0 comments on commit 29f1ed1

Please sign in to comment.