Skip to content

Commit

Permalink
Add l1 verifier
Browse files Browse the repository at this point in the history
Key additions and modifications:

- Add the L1HeadKey key to the database. It holds the latest core.L1Head
- Add blockchain.SetL1Head
- The l1 package contains most of the new logic.
- We mock the l1.Subscriber interface in tests.
  In practice, the interface is implemented by the l1.EthSubscriber, which
  is uses go-ethereum's ethclient and the generated
  internal/contract/starknet.go.
- codecov should ignore the generated l1/contract/starknet.go file.

Workflow:

node.Run -> l1.Client.Run -> (update is received from subscription) -> blockchain.SetL1Head

Co-authored-by: Wojciech Zieba <wojciech.zieba@nethermind.io>
  • Loading branch information
2 people authored and IronGauntlets committed Jun 8, 2023
1 parent 5670d77 commit c91c58c
Show file tree
Hide file tree
Showing 21 changed files with 1,174 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ coverage:
target: 62%
threshold: 2%
only_pulls: true
ignore:
- mocks
- l1/internal/contract/starknet.go
2 changes: 1 addition & 1 deletion .github/workflows/smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ jobs:
env:
TARGET_BLOCK: 100
TIMEOUT: 5m
JUNO_PARAMETERS: "--network mainnet"
JUNO_PARAMETERS: "--network mainnet --eth-node ${{ secrets.ETH_NODE }}"
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,13 @@ docker run -d \
-v /home/juno:/var/lib/juno \
nethermind/juno \
--rpc-port 6060 \
--db-path /var/lib/juno
--db-path /var/lib/juno \
--eth-node <YOUR-ETH-NODE>
```

You should replace `<YOUR-ETH-NODE> `with your actual Ethereum node address.
If you're using Infura, your Ethereum node address might look something like: `wss://mainnet.infura.io/ws/v3/your-infura-project-id`.

To view logs from the Docker container, use the following command:

```shell
Expand Down Expand Up @@ -139,7 +143,7 @@ The focus of Phase 2 will be to Verify the state from layer 1 and implement the
* [X] Starknet v0.11.0 support
* [X] Poseidon state trie support
* [ ] Blockchain: implement blockchain reorganization logic.
* [ ] Synchronisation: implement verification of state from layer 1.
* [X] Synchronisation: implement verification of state from layer 1.
* [ ] JSON-RPC API [v0.3.0](https://github.com/starkware-libs/starknet-specs/tree/v0.3.0-rc1):
* [ ] Implement the remaining endpoints:
* [X] `starknet_syncing`
Expand Down
22 changes: 22 additions & 0 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,28 @@ func (b *Blockchain) Receipt(hash *felt.Felt) (*core.TransactionReceipt, *felt.F
})
}

func (b *Blockchain) L1Head() (*core.L1Head, error) {
var update *core.L1Head
if err := b.database.View(func(txn db.Transaction) error {
return txn.Get(db.L1Height.Key(), func(updateBytes []byte) error {
return encoder.Unmarshal(updateBytes, &update)
})
}); err != nil {
return nil, err
}
return update, nil
}

func (b *Blockchain) SetL1Head(update *core.L1Head) error {
updateBytes, err := encoder.Marshal(update)
if err != nil {
return err
}
return b.database.Update(func(txn db.Transaction) error {
return txn.Set(db.L1Height.Key(), updateBytes)
})
}

// Store takes a block and state update and performs sanity checks before putting in the database.
func (b *Blockchain) Store(block *core.Block, stateUpdate *core.StateUpdate, newClasses map[felt.Felt]core.Class) error {
return b.database.Update(func(txn db.Transaction) error {
Expand Down
23 changes: 23 additions & 0 deletions blockchain/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,3 +498,26 @@ func TestEvents(t *testing.T) {
require.NoError(t, filter.Close())
})
}

func TestL1Update(t *testing.T) {
heads := []*core.L1Head{
{
BlockNumber: 1,
StateRoot: new(felt.Felt).SetUint64(2),
},
{
BlockNumber: 2,
StateRoot: new(felt.Felt).SetUint64(3),
},
}

for _, head := range heads {
t.Run(fmt.Sprintf("update L1 head to block %d", head.BlockNumber), func(t *testing.T) {
chain := blockchain.New(pebble.NewMemTest(), utils.MAINNET, utils.NewNopZapLogger())
require.NoError(t, chain.SetL1Head(head))
got, err := chain.L1Head()
require.NoError(t, err)
assert.Equal(t, head, got)
})
}
}
5 changes: 5 additions & 0 deletions cmd/juno/juno.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ const (
rpcPortF = "rpc-port"
dbPathF = "db-path"
networkF = "network"
ethNodeF = "eth-node"
pprofF = "pprof"
colourF = "colour"

defaultConfig = ""
defaultRPCPort = uint16(6060)
defaultDBPath = ""
defaultEthNode = ""
defaultPprof = false
defaultColour = true

Expand All @@ -47,6 +49,8 @@ const (
networkUsage = "Options: mainnet, goerli, goerli2, integration."
pprofUsage = "Enables the pprof server and listens on port 9080."
colourUsage = "Uses --colour=false command to disable colourized outputs (ANSI Escape Codes)."
ethNodeUsage = "Address to the Ethereum node. In order to verify the correctness of the L2 chain, " +
"Juno must connect to an Ethereum node and parse events in the Starknet contract."
)

var Version string
Expand Down Expand Up @@ -127,6 +131,7 @@ func NewCmd(config *node.Config, run func(*cobra.Command, []string) error) *cobr
junoCmd.Flags().Uint16(rpcPortF, defaultRPCPort, rpcPortUsage)
junoCmd.Flags().String(dbPathF, defaultDBPath, dbPathUsage)
junoCmd.Flags().Var(&defaultNetwork, networkF, networkUsage)
junoCmd.Flags().String(ethNodeF, defaultEthNode, ethNodeUsage)
junoCmd.Flags().Bool(pprofF, defaultPprof, pprofUsage)
junoCmd.Flags().Bool(colourF, defaultColour, colourUsage)

Expand Down
11 changes: 11 additions & 0 deletions core/felt/felt.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,14 @@ func (z *Felt) Mul(x, y *Felt) *Felt {
func (z *Felt) Cmp(x *Felt) int {
return z.val.Cmp(&x.val)
}

// SetBigInt forwards the call to underlying field element implementation
func (z *Felt) SetBigInt(v *big.Int) *Felt {
z.val.SetBigInt(v)
return z
}

// Uint64 forwards the call to underlying field element implementation
func (z *Felt) Uint64() uint64 {
return z.val.Uint64()
}
9 changes: 9 additions & 0 deletions core/l1_head.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package core

import "github.com/NethermindEth/juno/core/felt"

type L1Head struct {
BlockNumber uint64
BlockHash *felt.Felt
StateRoot *felt.Felt
}
1 change: 1 addition & 0 deletions db/buckets.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
ContractNonceHistory
ContractClassHashHistory
ContractDeploymentHeight
L1Height
)

// Key flattens a prefix and series of byte arrays into a single []byte.
Expand Down
15 changes: 14 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,28 @@ require gopkg.in/yaml.v2 v2.4.0 // indirect

require (
github.com/DataDog/zstd v1.4.5 // indirect
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.9.0 // indirect
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f // indirect
github.com/cockroachdb/redact v1.1.3 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/getsentry/sentry-go v0.13.0 // indirect
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/klauspost/compress v1.15.15 // indirect
Expand All @@ -57,20 +65,25 @@ require (
github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.3.0 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20200513190911-00229845015e // indirect
golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.3.8 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)
Loading

0 comments on commit c91c58c

Please sign in to comment.