forked from erigontech/erigon
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* deploy_cairo_smartcontract * deploy_cairo_smartcontract / 2 Add new transaction type for cairo and vm factory * starknet_getcode * deploy_cairo_smartcontract / 3 * deploy_cairo_smartcontract / 4 * deploy_cairo_smartcontract / 5 Co-authored-by: Aleksandr Borodulin <a.borodulin@axioma.lv>
- Loading branch information
1 parent
623a576
commit bbb3cc9
Showing
40 changed files
with
1,248 additions
and
242 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package commands | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/ledgerwatch/erigon/common" | ||
"github.com/ledgerwatch/erigon/common/hexutil" | ||
"github.com/ledgerwatch/erigon/rpc" | ||
"github.com/ledgerwatch/erigon/turbo/adapter" | ||
"github.com/ledgerwatch/erigon/turbo/rpchelper" | ||
) | ||
|
||
// GetCode implements starknet_getCode. Returns the byte code at a given address (if it's a smart contract). | ||
func (api *StarknetImpl) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { | ||
tx, err1 := api.db.BeginRo(ctx) | ||
if err1 != nil { | ||
return nil, fmt.Errorf("getCode cannot open tx: %w", err1) | ||
} | ||
defer tx.Rollback() | ||
blockNumber, _, err := rpchelper.GetBlockNumber(blockNrOrHash, tx, api.filters) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
reader := adapter.NewStateReader(tx, blockNumber) | ||
acc, err := reader.ReadAccountData(address) | ||
if acc == nil || err != nil { | ||
return hexutil.Bytes(""), nil | ||
} | ||
res, err := reader.ReadAccountCode(address, acc.Incarnation, acc.CodeHash) | ||
if res == nil || err != nil { | ||
return hexutil.Bytes(""), nil | ||
} | ||
if res == nil { | ||
return hexutil.Bytes(""), nil | ||
} | ||
return res, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package commands | ||
|
||
import ( | ||
"context" | ||
"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool" | ||
"github.com/ledgerwatch/erigon/common/hexutil" | ||
"github.com/ledgerwatch/erigon/rpc" | ||
|
||
"github.com/ledgerwatch/erigon-lib/kv" | ||
"github.com/ledgerwatch/erigon/common" | ||
) | ||
|
||
type StarknetAPI interface { | ||
SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) | ||
GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) | ||
} | ||
|
||
type StarknetImpl struct { | ||
*BaseAPI | ||
txPool txpool.TxpoolClient | ||
db kv.RoDB | ||
} | ||
|
||
func NewStarknetAPI(base *BaseAPI, db kv.RoDB, txPool txpool.TxpoolClient) *StarknetImpl { | ||
return &StarknetImpl{ | ||
BaseAPI: base, | ||
db: db, | ||
txPool: txPool, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package commands | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"fmt" | ||
txPoolProto "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool" | ||
"github.com/ledgerwatch/erigon/common" | ||
"github.com/ledgerwatch/erigon/common/hexutil" | ||
"github.com/ledgerwatch/erigon/core/types" | ||
"github.com/ledgerwatch/erigon/rlp" | ||
) | ||
|
||
var ( | ||
ErrOnlyStarknetTx = errors.New("only support starknet transactions") | ||
ErrOnlyContractDeploy = errors.New("only support contract creation") | ||
) | ||
|
||
// SendRawTransaction deploy new cairo contract | ||
func (api *StarknetImpl) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) { | ||
txn, err := types.DecodeTransaction(rlp.NewStream(bytes.NewReader(encodedTx), uint64(len(encodedTx)))) | ||
|
||
if err != nil { | ||
return common.Hash{}, err | ||
} | ||
|
||
if !txn.IsStarkNet() { | ||
return common.Hash{}, ErrOnlyStarknetTx | ||
} | ||
|
||
if !txn.IsContractDeploy() { | ||
return common.Hash{}, ErrOnlyContractDeploy | ||
} | ||
|
||
hash := txn.Hash() | ||
res, err := api.txPool.Add(ctx, &txPoolProto.AddRequest{RlpTxs: [][]byte{encodedTx}}) | ||
if err != nil { | ||
return common.Hash{}, err | ||
} | ||
|
||
if res.Imported[0] != txPoolProto.ImportResult_SUCCESS { | ||
return hash, fmt.Errorf("%s: %s", txPoolProto.ImportResult_name[int32(res.Imported[0])], res.Errors[0]) | ||
} | ||
|
||
return common.Hash{}, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# How to deploy cairo smart contract | ||
|
||
1. Compile cairo smart contract | ||
|
||
`starknet-compile contract.cairo --output contract_compiled.json --abi contract_abi.json` | ||
|
||
|
||
2. Generate payload for `starknet_sendRawTransaction` PRC method | ||
|
||
`go run ./cmd/starknet/main.go generateRawTx -c ./cairo/contract.json -o /cairo/send_raw_transaction -k b9a8b19ff082a7f4b943fcbe0da6cce6ce2c860090f05d031f463412ab534e95` | ||
|
||
Command syntax: `go run main.go generateRawTx --help` | ||
|
||
|
||
3. Use command output in RPC call | ||
|
||
```json | ||
"params":["0x03f86583127ed80180800180019637623232363136323639323233613230356235643764c080a0b44c2f4e18ca27e621171da5cf3a0c875c0749c7b998ec2759974280d987143aa04f01823122d972baa1a03b113535d9f9057fd9366fd8770e766b91f835b88ea6"], | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"encoding/hex" | ||
"fmt" | ||
"github.com/ledgerwatch/erigon/cmd/starknet/services" | ||
"github.com/spf13/cobra" | ||
"os" | ||
"strings" | ||
) | ||
|
||
type Flags struct { | ||
Contract string | ||
PrivateKey string | ||
Output string | ||
} | ||
|
||
var generateRawTxCmd = &cobra.Command{ | ||
Use: "generateRawTx", | ||
Short: "Generate data for starknet_sendRawTransaction RPC method", | ||
} | ||
|
||
func init() { | ||
flags := Flags{} | ||
|
||
generateRawTxCmd.Flags().StringVarP(&flags.Contract, "contract", "c", "", "Path to compiled cairo contract in JSON format") | ||
generateRawTxCmd.MarkFlagRequired("contract") | ||
|
||
generateRawTxCmd.Flags().StringVarP(&flags.PrivateKey, "private_key", "k", "", "Private key") | ||
generateRawTxCmd.MarkFlagRequired("private_key") | ||
|
||
generateRawTxCmd.Flags().StringVarP(&flags.Output, "output", "o", "", "Path to file where sign transaction will be saved") | ||
|
||
generateRawTxCmd.RunE = func(cmd *cobra.Command, args []string) error { | ||
rawTxGenerator := services.NewRawTxGenerator(flags.PrivateKey) | ||
|
||
fs := os.DirFS("/") | ||
buf := bytes.NewBuffer(nil) | ||
err := rawTxGenerator.CreateFromFS(fs, strings.Trim(flags.Contract, "/"), buf) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if flags.Output != "" { | ||
outputFile, err := os.Create(flags.Output) | ||
if err != nil { | ||
return fmt.Errorf("could not create output file: %v", flags.Output) | ||
} | ||
defer outputFile.Close() | ||
|
||
_, err = outputFile.WriteString(hex.EncodeToString(buf.Bytes())) | ||
if err != nil { | ||
return fmt.Errorf("could not write to output file: %v", flags.Output) | ||
} | ||
} else { | ||
fmt.Println(hex.EncodeToString(buf.Bytes())) | ||
} | ||
|
||
return err | ||
} | ||
|
||
rootCmd.AddCommand(generateRawTxCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// rootCmd represents the base command when called without any subcommands | ||
var rootCmd = &cobra.Command{ | ||
Use: "starknet", | ||
Short: "Starknet cli commands", | ||
} | ||
|
||
func Execute() { | ||
cobra.CheckErr(rootCmd.Execute()) | ||
} | ||
|
||
func init() { | ||
cobra.OnInitialize() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package main | ||
|
||
import "github.com/ledgerwatch/erigon/cmd/starknet/cmd" | ||
|
||
func main() { | ||
cmd.Execute() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package services | ||
|
||
import ( | ||
"encoding/hex" | ||
"errors" | ||
"github.com/holiman/uint256" | ||
"github.com/ledgerwatch/erigon/core/types" | ||
"github.com/ledgerwatch/erigon/crypto" | ||
"github.com/ledgerwatch/erigon/params" | ||
"golang.org/x/crypto/sha3" | ||
"io" | ||
"io/fs" | ||
) | ||
|
||
var ( | ||
ErrReadContract = errors.New("contract read error") | ||
ErrInvalidPrivateKey = errors.New("invalid private key") | ||
) | ||
|
||
func NewRawTxGenerator(privateKey string) RawTxGenerator { | ||
return RawTxGenerator{ | ||
privateKey: privateKey, | ||
} | ||
} | ||
|
||
type RawTxGenerator struct { | ||
privateKey string | ||
} | ||
|
||
func (g RawTxGenerator) CreateFromFS(fileSystem fs.FS, contractFileName string, writer io.Writer) error { | ||
privateKey, err := crypto.HexToECDSA(g.privateKey) | ||
if err != nil { | ||
return ErrInvalidPrivateKey | ||
} | ||
|
||
contract, err := fs.ReadFile(fileSystem, contractFileName) | ||
if err != nil { | ||
return ErrReadContract | ||
} | ||
|
||
enc := make([]byte, hex.EncodedLen(len(contract))) | ||
hex.Encode(enc, contract) | ||
|
||
tx := types.CairoTransaction{ | ||
CommonTx: types.CommonTx{ | ||
Nonce: 1, | ||
Value: uint256.NewInt(1), | ||
Gas: 1, | ||
Data: enc, | ||
}, | ||
} | ||
|
||
signature, _ := crypto.Sign(sha3.New256().Sum(nil), privateKey) | ||
signer := types.MakeSigner(params.FermionChainConfig, 1) | ||
|
||
signedTx, err := tx.WithSignature(*signer, signature) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = signedTx.MarshalBinary(writer) | ||
if err != nil { | ||
return errors.New("can not save signed tx") | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.