Skip to content

Commit

Permalink
Merge branch 'BlocSoc-iitr:v0.1' into v0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
x-senpai-x authored Sep 22, 2024
2 parents 21f942d + 10bc5b7 commit 6ef21f1
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 121 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: Test
run: make unit
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Blockchain Society IIT Roorkee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
102 changes: 3 additions & 99 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,101 +1,5 @@
# [Athena](https://github.com/BlocSoc-iitr/Athena/tree/main/athena)
# Athena

Go package for interacting with starknet. It is a tool which can be used in cli for the following tasks
> ⚠️ This project is undergoing heavy development and is still on its early stages. There will be constant breaking changes.
This is inspired from nethermind/entro but implemented in GoLang and is therefore much faster than Entro.
Unlike entro which is limited to being a cli tool , We have implemented frontend as well for Athena(Currently limited to backfilling )
We plan to make the frontend fully functional soon.

The below graph compares the backfilling time taken by Athena and Entro .




![Graph](https://github.com/user-attachments/assets/f051e42b-9676-48fc-9144-ea4d36bec75b)







## Tasks it can perform

- Backfill full blocks including events , tx & receipts
- Get implementation history
- ABI Decoding
- Decoding of functions & events from a transaction



# Usage/Examples

## Specify this in the following fields
from :- block number

to :- block number

jsonRpcUrl - https://rpc.nethermind.io/mainnet-juno?x-apikey=YOUR_API_KEY

output :- your_file_name.csv


## [ ABI Decoder](https://github.com/BlocSoc-iitr/Athena/blob/main/athena/decoder/abi_decoder.go)
abi parser , to parse each event and function ie to get its name and parameters and their datatype to help us in decoding

```bash
go run cli/get/starknet.go --classHash 0x01a736d6ed154502257f02b1ccdf4d9d1089f80811cd6acad48e6b6a9d1f2003 --jsonRpcUrl "https://rpc.nethermind.io/mainnet-juno?x-apikey=MIkLH4AOTdTH9uqu8PqvSHUBNnAnMU1fXdROa3qc1DsSVxvOcGRrwr6kSj1zsNjT" --decode
```
Result - list of functions and events decoded in that ABI to your console.
![WhatsApp Image 2024-09-08 at 16 35 46_eddf7e15](https://github.com/user-attachments/assets/03e55c8f-b7d6-4b60-81cf-316b2489b175)


## [ Event Decoder](https://github.com/BlocSoc-iitr/Athena/blob/main/athena/decoder/event_decoder.go)
To decode an event , user provides the contract hash and the name of the event and block range , firstly the abi is fetched and parsed and the data for the particular event and block range is fetched
The data fetched contains the keys and data required to decode the event , the decoder then initiates a new decoder class for that particular event and the event’s data is decoded with the provided inputs of hash,block range and event name


```bash
go run cli/get/dispatcher.go -event TransactionExecuted -contract 0x005a708f9c84bc709e967086572c6655e2b85eaf5a2ef752d92e24e64c5e392c_1 -from 691000 -to 692000
```
Result -


## [Function Decoder](https://github.com/BlocSoc-iitr/Athena/blob/main/athena/decoder/function_decoder.go)
Similar as above but instead of keys and data pairs we give call data as input that we will fetch in the provided blockrange



## [Backfill Events](https://github.com/BlocSoc-iitr/Athena/tree/main/athena/backfill/importers)

From - Block Number

To - Block Number


```bash
go run cli/backfill/starknet_events.go --from 67800 --to 67801 --rpc-url https://starknet-mainnet.public.blastapi.io/rpc/v0_7 --output events.csv --chunk-size 100
```

[With Filters](https://github.com/BlocSoc-iitr/Athena/blob/main/athena/backfill/filters.go)
```bash
go run cli/backfill/starknet_filters.go -rpc-url "https://rpc.nethermind.io/mainnet-juno?x-apikey=MIkLH4AOTdTH9uqu8PqvSHUBNnAnMU1fXdROa3qc1DsSVxvOcGRrwr6kSj1zsNjT" -contract-address "0x01a736d6ed154502257f02b1ccdf4d9d1089f80811cd6acad48e6b6a9d1f2003" -from 100000 -to 200000 -output "filtered_events.csv"
```

Result - all events decoded in your excel file

![WhatsApp Image 2024-09-08 at 16 35 46_05437c77](https://github.com/user-attachments/assets/3e2b20cd-f70f-4792-bcf2-dceb7e11d1fe)


## [Backfill full blocks](https://github.com/BlocSoc-iitr/Athena/blob/main/athena/backfill/importers/starknet.go)

```bash
go run starknet.go --from 110 --to 130 --rpc-url https://rpc.nethermind.io/mainnet-juno?x-apikey=MIkLH4AOTdTH9uqu8PqvSHUBNnAnMU1fXdROa3qc1DsSVxvOcGRrwr6kSj1zsNjT --output blocks_details.csv --transactionhash (for block data)
```
Result - all blocks , transaction hashes , receipts & events of that txns data in your csv files.

## [Backfill with filters](https://github.com/BlocSoc-iitr/Athena/blob/main/athena/backfill/filters.go)



![WhatsApp Image 2024-09-08 at 16 36 25_74cfd3e6](https://github.com/user-attachments/assets/ea0d53a9-42ab-4394-9963-b059f9b40ed6)
This project aims to implement a blockchain data decoder using Go. This is one of the [other](https://github.com/NethermindEth/entro) implementations that are being developed in python.
13 changes: 9 additions & 4 deletions athena_abi/cairo_type_decoders_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@ func TestArrayDecoding(t *testing.T) {
for i := 0; i < len(test.decoded); i++ {
assert.Equal(t, test.decoded[i], decodedValues[i])
}
// encodedCalldata, err := EncodeFromTypes([]StarknetType{test.starknetType}, []interface{}{test.decoded})
// assert.Equal(t, err, nil)
// assert.Equal(t, test.calldata, encodedCalldata)
// assert.Equal(t, 0, len(_calldata))
// needed to convert []*big.Int into []interface{}
interfaceSlice := make([]interface{}, len(test.decoded))
for i, v := range test.decoded {
interfaceSlice[i] = v
}
encodedCalldata, err := EncodeFromTypes([]StarknetType{test.starknetType}, []interface{}{interfaceSlice})
assert.Equal(t, nil, err)
assert.Equal(t, test.calldata, encodedCalldata)
assert.Equal(t, 0, len(_calldata))
}
}
160 changes: 160 additions & 0 deletions athena_abi/core.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package athena_abi

import (
"errors"
"log"
)

type StarknetABI struct {
ABIName *string
ClassHash []byte
Functions map[string]AbiFunction
Events map[string]AbiEvent
Constructor []AbiParameter
L1Handler *AbiFunction
ImplementedInterfaces map[string]AbiInterface
}

// Declare errors
var (
errParseDefinedTypes = errors.New("unable to parse defined types")
errParseInterfaces = errors.New("unable to parse interfaces")
errParseFunctions = errors.New("unable to parse functions")
errParseEvents = errors.New("unable to parse events")
errParseConstructor = errors.New("unable to parse constructor")
errParseL1Handler = errors.New("unable to parse L1 handler")
errParseImplementedInterfaces = errors.New("unable to parse implemented interfaces")
)

// Parse Starknet ABI from JSON
// @param abiJSON
// @param abiname
// @param classHash
func StarknetAbiFromJSON(abiJson []map[string]interface{}, abiName string, classHash []byte) (*StarknetABI, error) {
groupedAbi := GroupAbiByType(abiJson)

// Parse defined types (structs and enums)
definedTypes, err := ParseEnumsAndStructs(groupedAbi["type_def"])
if err != nil {
sortedDefs, errDef := TopoSortTypeDefs(groupedAbi["type_def"])
if errDef == nil {
defineTypes, errDtypes := ParseEnumsAndStructs(sortedDefs)
definedTypes = defineTypes
errDef = errDtypes
}
if errDef != nil {
return nil, errParseDefinedTypes
}
log.Println("ABI Struct and Enum definitions out of order & required topological sorting")
}

// Parse interfaces
var definedInterfaces []AbiInterface
for _, iface := range groupedAbi["interface"] {
functions := []AbiFunction{}
for _, funcData := range iface["items"].([]interface{}) {
parsedAbi, errWhileParsing := ParseAbiFunction(funcData.(map[string]interface{}), definedTypes)
if errWhileParsing != nil {
return nil, errParseInterfaces
}
functions = append(functions, *parsedAbi)
}
definedInterfaces = append(definedInterfaces, AbiInterface{
name: iface["name"].(string),
functions: functions,
})
}

// Parse functions
functions := make(map[string]AbiFunction)
for _, functionData := range groupedAbi["function"] {
funcName := functionData["name"].(string)
abiFunc, errParsingFunctions := ParseAbiFunction(functionData, definedTypes)
if errParsingFunctions != nil {
return nil, errParseFunctions
}
functions[funcName] = *abiFunc
}

// Add functions from interfaces
for _, iface := range definedInterfaces {
for _, function := range iface.functions {
functions[function.name] = function
}
}

// Parse events
parsedAbiEvents := []AbiEvent{}
for _, eventData := range groupedAbi["event"] {
parsedEvent, errParsingEvent := ParseAbiEvent(eventData, definedTypes)
if errParsingEvent != nil {
return nil, errParseEvents
}
parsedAbiEvents = append(parsedAbiEvents, *parsedEvent)
}

events := make(map[string]AbiEvent)
for _, event := range parsedAbiEvents {
if event.name != "" {
events[event.name] = event
}
}

// Parse constructor
var constructor []AbiParameter
if len(groupedAbi["constructor"]) == 1 {
for _, paramData := range groupedAbi["constructor"][0]["inputs"].([]interface{}) {
param := paramData.(map[string]interface{})
typed, errorParsingType := parseType(param["type"].(string), definedTypes)
if errorParsingType != nil {
return nil, errParseConstructor
}
constructor = append(constructor, AbiParameter{
Name: param["name"].(string),
Type: typed,
})
}
} else {
constructor = nil
}

// Parse L1 handler
var l1Handler *AbiFunction
if len(groupedAbi["l1_handler"]) == 1 {
handler, errorParsingFunction := ParseAbiFunction(groupedAbi["l1_handler"][0], definedTypes)
if errorParsingFunction != nil {
return nil, errParseL1Handler
}
l1Handler = handler
} else {
l1Handler = nil
}

// Parse implemented interfaces
implementedInterfaces := make(map[string]AbiInterface)
implArray, ok := groupedAbi["impl"]
if !ok {
return nil, errParseImplementedInterfaces
}
for _, implData := range implArray {
implMap := implData
if ifaceName, ok := implMap["interface_name"].(string); ok {
for _, iface := range definedInterfaces {
if iface.name == ifaceName {
implementedInterfaces[iface.name] = iface
}
}
}
}

// Return the populated StarknetAbi struct
return &StarknetABI{
ABIName: &abiName,
ClassHash: classHash,
Functions: functions,
Events: events,
Constructor: constructor,
L1Handler: l1Handler,
ImplementedInterfaces: implementedInterfaces,
}, nil
}
19 changes: 10 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/BlocSoc-iitr/Athena

go 1.22.5
go 1.21

require (
github.com/NethermindEth/starknet.go v0.7.0
Expand All @@ -10,7 +10,13 @@ require (
require (
github.com/NethermindEth/juno v0.3.1
github.com/ethereum/go-ethereum v1.14.8
github.com/go-sql-driver/mysql v1.8.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.11.0
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.25.7
gorm.io/datatypes v1.2.1
gorm.io/driver/mysql v1.5.6
gorm.io/gorm v1.25.11
)

Expand All @@ -21,32 +27,27 @@ require (
github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/holiman/uint256 v1.3.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/test-go/testify v1.1.4 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.23.0 // indirect
golang.org/x/text v0.17.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.6 // indirect
)
Loading

0 comments on commit 6ef21f1

Please sign in to comment.