Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
nordschesasa committed Mar 13, 2024
0 parents commit ea7687a
Show file tree
Hide file tree
Showing 12 changed files with 1,037 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# docker build . -t ghcr.io/reddio-com/eth_logcache:latest
FROM golang:1.22-bookworm as builder

RUN mkdir /build
COPY . /build
RUN cd /build && go build .

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y ca-certificates && apt-get clean

RUN mkdir /data
COPY --from=builder /build/main /logcache

CMD ["/logcache"]
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# ETH LogCache

## Usage

### Start the service using Docker Compose

```
docker-compose up -d
```

or, you can build and run with environment variables:

```
RPC_URL=https://eth-mainnet.reddio.com START_BLOCK=15560257 go run .
```

### Send request to ETH LogCache

```sh
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"method": "eth_getLogs",
"params": [
{
"fromBlock": "0x0",
"toBlock": "0x120dc53",
"address": "0xb62bcd40a24985f560b5a9745d478791d8f1945c",
"topics": [
[
"0xcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d2"
]
]
}
],
"id": 62,
"jsonrpc": "2.0"
}' \
http://localhost:3000
```

Response:
```json
{"block_number":[{"id":62,"jsonrpc":"2.0","result":[{"address":"0xb62bcd40a24985f560b5a9745d478791d8f1945c","blockHash":"0xb1c05e3a5f7791b40d9ded2bb67bd2d250f1ccb036dac0f6a046b7ed2d416df0","blockNumber":"0xed6e42","data":"0x0000000000000000000000006b7763b749073e892c83e674c1ec4799d6f339ef","logIndex":"0x151","removed":false,"topics":["0xcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d2"],"transactionHash":"0x87130dfe52f1eb4ec22261333534ee7ac2c15e5256ffa7a59ae7153119c6cd73","transactionIndex":"0xc9"},{"address":"0xb62bcd40a24985f560b5a9745d478791d8f1945c","blockHash":"0xb1c05e3a5f7791b40d9ded2bb67bd2d250f1ccb036dac0f6a046b7ed2d416df0","blockNumber":"0xed6e42","data":"0x0000000000000000000000006ea99c6fe2c770c2c46ebe03a4855977282e844f","logIndex":"0x153","removed":false,"topics":["0xcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d2"],"transactionHash":"0xca00caf8ad277bd23597d497e1c77b4308d40e8787d7e0e5204d320f1f3ab31c","transactionIndex":"0xcb"}]}]}
```

## License

MIT
148 changes: 148 additions & 0 deletions TEST_LOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
## Timeout Request

Origin Request:

* 0x0 -> 0
* 0x120dc53 -> 18930771

```json
{
"method": "eth_getLogs",
"params": [
{
"fromBlock": "0x0",
"toBlock": "0x120dc53",
"address": "0xb62bcd40a24985f560b5a9745d478791d8f1945c",
"topics": [
[
"0xcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d2"
]
]
}
],
"id": 62,
"jsonrpc": "2.0"
}
```

Response:

```json
{
"jsonrpc": "2.0",
"id": 62,
"result": [
{
"address": "0xb62bcd40a24985f560b5a9745d478791d8f1945c",
"blockHash": "0xb1c05e3a5f7791b40d9ded2bb67bd2d250f1ccb036dac0f6a046b7ed2d416df0",
"blockNumber": "0xed6e42",
"data": "0x0000000000000000000000006b7763b749073e892c83e674c1ec4799d6f339ef",
"logIndex": "0x151",
"removed": false,
"topics": [
"0xcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d2"
],
"transactionHash": "0x87130dfe52f1eb4ec22261333534ee7ac2c15e5256ffa7a59ae7153119c6cd73",
"transactionIndex": "0xc9"
},
{
"address": "0xb62bcd40a24985f560b5a9745d478791d8f1945c",
"blockHash": "0xb1c05e3a5f7791b40d9ded2bb67bd2d250f1ccb036dac0f6a046b7ed2d416df0",
"blockNumber": "0xed6e42",
"data": "0x0000000000000000000000006ea99c6fe2c770c2c46ebe03a4855977282e844f",
"logIndex": "0x153",
"removed": false,
"topics": [
"0xcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d2"
],
"transactionHash": "0xca00caf8ad277bd23597d497e1c77b4308d40e8787d7e0e5204d320f1f3ab31c",
"transactionIndex": "0xcb"
}
]
}
```



## Verify Request

Original Request:

* 0x121AE54 -> 18984532
* 0x121e2be -> 18997950

```json
{
"method": "eth_getLogs",
"params": [
{
"fromBlock": "0x121AE54",
"toBlock": "0x121e2be",
"address": "0x15e6e0d4ebeac120f9a97e71faa6a0235b85ed12",
"topics": [
[
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
]
]
}
],
"id": 62,
"jsonrpc": "2.0"
}
```

Response:

```json
{
"jsonrpc": "2.0",
"id": 62,
"result": [
{
"address": "0x15e6e0d4ebeac120f9a97e71faa6a0235b85ed12",
"blockHash": "0xbca59ccc09a7bb1e6877c943fce30e7d3482cc461769d98f5b7ede1d36e02463",
"blockNumber": "0x121ae54",
"data": "0x0000000000000000000000000000000000000000000000006e2255f409800000",
"logIndex": "0xa9",
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x000000000000000000000000f328a29acc598ff8a399e45d8b11be22ef6d3987"
],
"transactionHash": "0xa6a4412d64971843db5babcf25b9f5644acd295be8ff3ebbdc38e61276b713dd",
"transactionIndex": "0x66"
},
{
"address": "0x15e6e0d4ebeac120f9a97e71faa6a0235b85ed12",
"blockHash": "0xacd6dda9c3030cef969feb8aa46730e7c929b2267b9b4291d680ed964f0a653e",
"blockNumber": "0x121e2be",
"data": "0x0000000000000000000000000000000000000000000000003782dace9d900000",
"logIndex": "0xaa",
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000f328a29acc598ff8a399e45d8b11be22ef6d3987",
"0x000000000000000000000000861e3c82bc2753ea64ae5f962d993df6853a6700"
],
"transactionHash": "0x6c42543f5371e174ba751acb41f8ef9f78366fb996646203bffa43b489606bf0",
"transactionIndex": "0x7d"
},
{
"address": "0x15e6e0d4ebeac120f9a97e71faa6a0235b85ed12",
"blockHash": "0xacd6dda9c3030cef969feb8aa46730e7c929b2267b9b4291d680ed964f0a653e",
"blockNumber": "0x121e2be",
"data": "0x0000000000000000000000000000000000000000000000003782dace9d900000",
"logIndex": "0xab",
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000861e3c82bc2753ea64ae5f962d993df6853a6700",
"0x0000000000000000000000000000000000000000000000000000000000000000"
],
"transactionHash": "0x6c42543f5371e174ba751acb41f8ef9f78366fb996646203bffa43b489606bf0",
"transactionIndex": "0x7d"
}
]
}
```
45 changes: 45 additions & 0 deletions chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"context"
"fmt"
"math/big"
)

func LatestBlockOnChain() (uint64, error) {
header, err := ETH_CLIENT.HeaderByNumber(context.Background(), nil)
if err != nil {
return 0, fmt.Errorf("Failed to get latest block header: %v", err)
}

return header.Number.Uint64(), nil
}

func getTopicListByBlockNumber(blockNumber uint64) ([]string, error) {
blockNumberBig := new(big.Int)
blockNumberBig.SetUint64(blockNumber)
block, err := ETH_CLIENT.BlockByNumber(context.Background(), blockNumberBig)
for err != nil {
fmt.Printf("Failed to get block: %v\n", err)
block, err = ETH_CLIENT.BlockByNumber(context.Background(), blockNumberBig)
}

totalTopics := make([]string, 0)

for _, tx := range block.Transactions() {
// fmt.Printf("Dealing with transaction: %s\n", tx.Hash().Hex())

receipt, err := ETH_CLIENT.TransactionReceipt(context.Background(), tx.Hash())
if err != nil {
return nil, fmt.Errorf("Failed to get transaction receipt: %v", err)
}

for _, log := range receipt.Logs {
for _, topic := range log.Topics {
totalTopics = append(totalTopics, topic.Hex())
}
}
}

return totalTopics, nil
}
133 changes: 133 additions & 0 deletions db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package main

import (
"encoding/binary"
"fmt"

"github.com/cockroachdb/pebble"
)

var (
DB *pebble.DB
)

func Uint64ArrayToByteSlice(array []uint64) []byte {
byteSlice := make([]byte, 8*len(array))
for i, v := range array {
binary.LittleEndian.PutUint64(byteSlice[i*8:], v)
}
return byteSlice
}

func ByteSliceToUint64Array(byteSlice []byte) []uint64 {
array := make([]uint64, len(byteSlice)/8)
for i := range array {
array[i] = binary.LittleEndian.Uint64(byteSlice[i*8:])
}
return array
}

func DeduplicateUint64Array(array []uint64) []uint64 {
keys := make(map[uint64]bool)
list := []uint64{}
for _, entry := range array {
if _, value := keys[entry]; !value {
keys[entry] = true
list = append(list, entry)
}
}
return list
}

func SetKeyNumberArray(key string, number uint64) error {
// Check if key exists, if exists, read array and append number to array
// If not exists, create array with number
keyByteSlice := []byte(key)
existingNumberArray, err := GetKeyNumberArray(key)
if err != nil {
return err
}
if existingNumberArray != nil {
// Append number to array
existingNumberArray = append(existingNumberArray, number)

// Deduplicate array
existingNumberArray = DeduplicateUint64Array(existingNumberArray)

numberByteSlice := Uint64ArrayToByteSlice(existingNumberArray)
err := DB.Set(keyByteSlice, numberByteSlice, pebble.NoSync)
if err != nil {
return err
}
return nil
} else {
// Create array with number
numberArray := []uint64{number}
numberByteSlice := Uint64ArrayToByteSlice(numberArray)
err := DB.Set(keyByteSlice, numberByteSlice, pebble.NoSync)
if err != nil {
return err
}
return nil
}
}

func SetKeyNumber(key string, number uint64) error {
keyByteSlice := []byte(key)
value := make([]byte, 8)
binary.LittleEndian.PutUint64(value, uint64(number))
err := DB.Set(keyByteSlice, value, pebble.Sync)
if err != nil {
return err
}
return nil
}

func GetKeyNumberArray(key string) ([]uint64, error) {
keyByteSlice := []byte(key)
value, closer, err := DB.Get(keyByteSlice)
if err != nil {
// Check if key is not found
if err == pebble.ErrNotFound {
return nil, nil
}
return nil, err
}
defer closer.Close()

numberArray := ByteSliceToUint64Array(value)
return numberArray, nil
}

func GetKeyNumber(key string) (uint64, error) {
keyByteSlice := []byte(key)
value, closer, err := DB.Get(keyByteSlice)
if err != nil {
// Check if key is not found
if err == pebble.ErrNotFound {
fmt.Printf("Key %s not found\n", key)
return 0, nil
}
}
defer closer.Close()

number := binary.LittleEndian.Uint64(value)
return number, nil
}

func FlushDB() error {
err := DB.Flush()
if err != nil {
return err
}
return nil
}

func LatestBlockNumberInDB() (uint64, error) {
key := "LatestBlockNumberInDB"
number, err := GetKeyNumber(key)
if err != nil {
return 0, err
}
return number, nil
}
Loading

0 comments on commit ea7687a

Please sign in to comment.