Skip to content

feature: implement consensus Proposer interface #2854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/benchmark-sync.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Benchmark Sync

on:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0' # Every Sunday at midnight UTC

permissions:
contents: read

env:
DOCKER_REGISTRY: nethermind.jfrog.io
IMAGE_REPO: nubia-oci-local-dev/juno
BENCHMARK_TAG: nubia-oci-local-dev/juno-benchmark:latest

jobs:
sync-benchmark:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Extract Git version
id: extract_version
run: echo "version=$(git describe --tags)" >> $GITHUB_OUTPUT

- name: Setup Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2
id: buildx

- name: Login to registry
run: docker login ${{ env.DOCKER_REGISTRY }} -u ${{ secrets.ARTIFACTORY_NUBIA_USERNAME }} -p ${{ secrets.ARTIFACTORY_NUBIA_TOKEN_DEVELOPER }}

- name: Create benchmark tag
run: docker buildx imagetools create -t ${{ env.DOCKER_REGISTRY }}/${{ env.BENCHMARK_TAG }} ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_REPO }}:${{ steps.extract_version.outputs.version }}

- name: Log out from Docker registry
run: docker logout ${{ env.DOCKER_REGISTRY }}
4 changes: 2 additions & 2 deletions .github/workflows/deploy-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ jobs:
needs: [deploy]
uses: ./.github/workflows/starknet-rs-tests.yml
secrets:
STARKNET_RPC: ${{ secrets.RPC_URL }}/v0_7?apikey=${{ secrets.AUTH_TOKEN }}
STARKNET_RPC: ${{ secrets.RPC_URL }}/v0_8?apikey=${{ secrets.AUTH_TOKEN }}

starknet-js:
needs: [deploy]
Expand All @@ -123,7 +123,7 @@ jobs:
needs: [deploy]
uses: ./.github/workflows/starknet-go-tests.yml
with:
ref: f8f0b717aa5b59c797540c0567f309ae78537e09
ref: 298264d89acbbd6611fcafa09c5b40acd9d35515
rpc_version: v0_8
secrets:
TEST_RPC_URL: ${{ secrets.RPC_URL }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/starknet-rs-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: xJonathanLEI/starknet-rs
ref: starknet/v0.12.0
ref: starknet/v0.15.0

- name: Setup Rust
uses: actions-rs/toolchain@v1
Expand Down
88 changes: 86 additions & 2 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,8 +622,16 @@
Number: 0,
SequencerAddress: &felt.Zero,
EventsBloom: core.EventsBloom(receipts),
L1GasPriceETH: &felt.Zero,
L1GasPriceSTRK: &felt.Zero,
L1GasPriceETH: new(felt.Felt).SetUint64(1),
L1GasPriceSTRK: new(felt.Felt).SetUint64(1),
L1DataGasPrice: &core.GasPrice{
PriceInWei: new(felt.Felt).SetUint64(1),
PriceInFri: new(felt.Felt).SetUint64(1),
},
L2GasPrice: &core.GasPrice{
PriceInWei: new(felt.Felt).SetUint64(1),
PriceInFri: new(felt.Felt).SetUint64(1),
},
},
Transactions: make([]core.Transaction, 0),
Receipts: receipts,
Expand All @@ -638,3 +646,79 @@
return nil, nil
})
}

// Simulate returns what the new completed header and state update would be if the
// provided block was added to the chain.
func (b *Blockchain) Simulate(
block *core.Block,
stateUpdate *core.StateUpdate,
newClasses map[felt.Felt]core.Class,
sign BlockSignFunc,
) (*core.Block, *core.StateUpdate, *core.BlockCommitments, *felt.Felt, error) {
var newBlock *core.Block
var newSU *core.StateUpdate
var newCommitments *core.BlockCommitments
var concatCount *felt.Felt

simulate := func(txn db.IndexedBatch) error {
if err := b.updateStateRoots(txn, block, stateUpdate, newClasses); err != nil {
return err
}

Check warning on line 666 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L665-L666

Added lines #L665 - L666 were not covered by tests
blockHash, commitments, err := core.BlockHash(
block,
stateUpdate.StateDiff,
b.network,
block.SequencerAddress)
if err != nil {
return err
}

Check warning on line 674 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L673-L674

Added lines #L673 - L674 were not covered by tests
block.Hash = blockHash
stateUpdate.BlockHash = blockHash

// Starknet consensus requires zero values for empty blocks
if block.TransactionCount == 0 {
newCommitments = &core.BlockCommitments{
TransactionCommitment: new(felt.Felt).SetUint64(0),
EventCommitment: new(felt.Felt).SetUint64(0),
ReceiptCommitment: new(felt.Felt).SetUint64(0),
StateDiffCommitment: new(felt.Felt).SetUint64(0),
}
concatCount = new(felt.Felt).SetUint64(0)
} else {
newCommitments = commitments
concatCount = core.ConcatCounts(
block.TransactionCount,
block.EventCount,
stateUpdate.StateDiff.Length(),
block.L1DAMode)
}

if err := b.signBlock(block, stateUpdate, sign); err != nil {
return err
}

Check warning on line 698 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L697-L698

Added lines #L697 - L698 were not covered by tests

if err := b.storeBlockData(txn, block, stateUpdate, commitments); err != nil {
return err
}

Check warning on line 702 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L701-L702

Added lines #L701 - L702 were not covered by tests

block, err := core.GetBlockByNumber(txn, block.Number)
if err != nil {
return err
}

Check warning on line 707 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L706-L707

Added lines #L706 - L707 were not covered by tests
su, err := core.GetStateUpdateByBlockNum(txn, block.Number)
if err != nil {
return err
}

Check warning on line 711 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L710-L711

Added lines #L710 - L711 were not covered by tests
newBlock = block
newSU = su
return nil
}

// Simulate without commit
txn := b.database.NewIndexedBatch()
if err := simulate(txn); err != nil {
return nil, nil, nil, nil, err
}

Check warning on line 721 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L720-L721

Added lines #L720 - L721 were not covered by tests
txn.Reset()
return newBlock, newSU, newCommitments, concatCount, nil
}
75 changes: 62 additions & 13 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"sync/atomic"
"time"

"github.com/Masterminds/semver/v3"
"github.com/NethermindEth/juno/adapters/vm2core"
"github.com/NethermindEth/juno/blockchain"
"github.com/NethermindEth/juno/core"
Expand Down Expand Up @@ -52,10 +53,13 @@
headCloser blockchain.StateCloser

finaliseMutex musync.RWMutex

protocolVersion semver.Version
}

func New(privKey *ecdsa.PrivateKey, ownAddr *felt.Felt, bc *blockchain.Blockchain, vm vm.VM,
blockTime time.Duration, mempool *mempool.Pool, log utils.Logger, disableFees bool, database db.KeyValueStore,
protocolVersion semver.Version,
) Builder {
return Builder{
ownAddress: *ownAddr,
Expand All @@ -72,6 +76,7 @@
subPendingBlock: feed.New[*core.Block](),
subReorgFeed: feed.New[*sync.ReorgBlockRange](),
finaliseMutex: musync.RWMutex{},
protocolVersion: protocolVersion,
}
}

Expand Down Expand Up @@ -167,6 +172,7 @@
return nil
}

// The current gas strategy is to just use the values from the previous block
func (b *Builder) InitPendingBlock() error {
header, err := b.bc.HeadsHeader()
if err != nil {
Expand All @@ -177,13 +183,12 @@
ParentHash: header.Hash,
Number: header.Number + 1,
SequencerAddress: &b.ownAddress,
L1GasPriceETH: felt.One.Clone(),
L1GasPriceSTRK: felt.One.Clone(),
L1DAMode: core.Calldata,
L1DataGasPrice: &core.GasPrice{
PriceInWei: felt.One.Clone(),
PriceInFri: felt.One.Clone(),
},
ProtocolVersion: b.protocolVersion.String(),
L1GasPriceETH: header.L1GasPriceETH,
L1GasPriceSTRK: header.L1GasPriceSTRK,
L1DAMode: core.Blob,
L1DataGasPrice: header.L1DataGasPrice,
L2GasPrice: header.L2GasPrice,
},
Transactions: []core.Transaction{},
Receipts: []*core.TransactionReceipt{},
Expand Down Expand Up @@ -297,7 +302,7 @@
return err
}
b.log.Debugw("running txns", userTxns)
if err = b.runTxns(userTxns, blockHashToBeRevealed); err != nil {
if _, err = b.runTxns(userTxns, blockHashToBeRevealed); err != nil {
b.log.Debugw("failed running txn", "err", err.Error())
var txnExecutionError vm.TransactionExecutionError
if !errors.As(err, &txnExecutionError) {
Expand Down Expand Up @@ -334,11 +339,11 @@

// runTxns executes the provided transaction and applies the state changes
// to the pending state
func (b *Builder) runTxns(txns []mempool.BroadcastedTransaction, blockHashToBeRevealed *felt.Felt) error {
func (b *Builder) runTxns(txns []mempool.BroadcastedTransaction, blockHashToBeRevealed *felt.Felt) (uint64, error) {
// Get the pending state
pending, err := b.Pending()
if err != nil {
return err
return 0, err

Check warning on line 346 in builder/builder.go

View check run for this annotation

Codecov / codecov/patch

builder/builder.go#L346

Added line #L346 was not covered by tests
}

// Create a state writer for the transaction execution
Expand Down Expand Up @@ -371,15 +376,15 @@
b.bc.Network(),
false, false, false, true, false)
if err != nil {
return err
return 0, err

Check warning on line 379 in builder/builder.go

View check run for this annotation

Codecov / codecov/patch

builder/builder.go#L379

Added line #L379 was not covered by tests
}

// Handle declared classes for declare transactions
for i, trace := range vmResults.Traces {
if trace.StateDiff.DeclaredClasses != nil ||
trace.StateDiff.DeprecatedDeclaredClasses != nil {
if err := b.processClassDeclaration(&txns[i], &state); err != nil {
return err
return 0, err

Check warning on line 387 in builder/builder.go

View check run for this annotation

Codecov / codecov/patch

builder/builder.go#L387

Added line #L387 was not covered by tests
}
}
}
Expand All @@ -397,7 +402,11 @@
// Update pending block with transaction results
updatePendingBlock(pending, receipts, coreTxns, mergedStateDiff)

return b.StorePending(pending)
l2GasConsumed := uint64(1) // Todo: should be 0?? Blockifer seems to return 0..
for i := range vmResults.GasConsumed {
l2GasConsumed += vmResults.GasConsumed[i].L2Gas
}
return l2GasConsumed, b.StorePending(pending)
}

// processClassDeclaration handles class declaration storage for declare transactions
Expand Down Expand Up @@ -463,3 +472,43 @@
func (b *Builder) SubscribePending() sync.PendingSubscription {
return sync.PendingSubscription{Subscription: b.subPendingBlock.Subscribe()}
}

func (b *Builder) MempoolIsEmpty() bool {
return b.mempool.Len() == 0
}

func (b *Builder) PopBatchTxns() ([]mempool.BroadcastedTransaction, error) {
return b.mempool.PopBatch(NumTxnsToBatchExecute)
}

func (b *Builder) ExecuteTxns(txns []mempool.BroadcastedTransaction) (uint64, error) {
b.finaliseMutex.RLock()
defer b.finaliseMutex.RUnlock()
b.log.Debugw("calling ExecuteTxns")
blockHashToBeRevealed, err := b.getRevealedBlockHash()
if err != nil {
return 0, err
}

Check warning on line 491 in builder/builder.go

View check run for this annotation

Codecov / codecov/patch

builder/builder.go#L490-L491

Added lines #L490 - L491 were not covered by tests

l2gasConsumed := uint64(0)
l2gasConsumed, err = b.runTxns(txns, blockHashToBeRevealed)
if err != nil {
b.log.Debugw("failed running txn", "err", err.Error())
return 0, err
}

Check warning on line 498 in builder/builder.go

View check run for this annotation

Codecov / codecov/patch

builder/builder.go#L496-L498

Added lines #L496 - L498 were not covered by tests
b.log.Debugw("running txns success")
return l2gasConsumed, nil
}

// ExecutePending updates the pending block and state-update
func (b *Builder) ExecutePending() (*core.BlockCommitments, *felt.Felt, error) {
pending, err := b.Pending()
if err != nil {
return nil, nil, err
}

Check warning on line 508 in builder/builder.go

View check run for this annotation

Codecov / codecov/patch

builder/builder.go#L507-L508

Added lines #L507 - L508 were not covered by tests
newBlock, newSU, commitments, concatCommitment, err := b.bc.Simulate(pending.Block, pending.StateUpdate, pending.NewClasses, nil)
pending.Block = newBlock
pending.StateUpdate = newSU
b.pendingBlock.Store(pending)
return commitments, concatCommitment, err
}
10 changes: 7 additions & 3 deletions builder/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"
"time"

"github.com/Masterminds/semver/v3"
"github.com/NethermindEth/juno/blockchain"
"github.com/NethermindEth/juno/builder"
"github.com/NethermindEth/juno/core"
Expand Down Expand Up @@ -86,7 +87,8 @@ func TestSign(t *testing.T) {
privKey, err := ecdsa.GenerateKey(rand.Reader)
require.NoError(t, err)
p := mempool.New(memory.New(), bc, 1000, utils.NewNopZapLogger())
testBuilder := builder.New(privKey, seqAddr, bc, mockVM, 0, p, utils.NewNopZapLogger(), false, testDB)
pVersion := semver.New(0, 13, 2, "", "")
testBuilder := builder.New(privKey, seqAddr, bc, mockVM, 0, p, utils.NewNopZapLogger(), false, testDB, *pVersion)

_, err = testBuilder.Sign(new(felt.Felt), new(felt.Felt))
require.NoError(t, err)
Expand All @@ -106,7 +108,8 @@ func TestBuildTwoEmptyBlocks(t *testing.T) {
p := mempool.New(memory.New(), bc, 1000, utils.NewNopZapLogger())

minHeight := uint64(2)
testBuilder := builder.New(privKey, seqAddr, bc, mockVM, time.Millisecond, p, utils.NewNopZapLogger(), false, testDB)
pVersion := semver.New(0, 13, 2, "", "")
testBuilder := builder.New(privKey, seqAddr, bc, mockVM, time.Millisecond, p, utils.NewNopZapLogger(), false, testDB, *pVersion)

ctx, cancel := context.WithCancel(t.Context())
go func() {
Expand Down Expand Up @@ -195,7 +198,8 @@ func TestPrefundedAccounts(t *testing.T) {
require.NoError(t, err)
require.NoError(t, bc.StoreGenesis(&diff, classes))
blockTime := 100 * time.Millisecond
testBuilder := builder.New(privKey, seqAddr, bc, vm.New(false, log), blockTime, p, log, false, testDB)
pVersion := semver.New(0, 13, 2, "", "")
testBuilder := builder.New(privKey, seqAddr, bc, vm.New(false, log), blockTime, p, log, false, testDB, *pVersion)
rpcHandler := rpc.New(bc, nil, nil, "", log).WithMempool(p)
for _, txn := range expectedExnsInBlock {
_, rpcErr := rpcHandler.AddTransaction(t.Context(), txn)
Expand Down
5 changes: 5 additions & 0 deletions consensus/proposer/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package proposer

import (
_ "github.com/NethermindEth/juno/encoder/registry"
)
Loading
Loading