Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2bcd6ba

Browse files
committedJun 10, 2025·
feature: implemet p2p2consensus adapters for proposal types
1 parent 0dc9888 commit 2bcd6ba

File tree

5 files changed

+459
-0
lines changed

5 files changed

+459
-0
lines changed
 

‎adapters/p2p2consensus/class.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package p2p2consensus
2+
3+
import (
4+
"github.com/NethermindEth/juno/adapters/sn2core"
5+
"github.com/NethermindEth/juno/core"
6+
"github.com/NethermindEth/juno/core/crypto"
7+
"github.com/NethermindEth/juno/starknet"
8+
"github.com/NethermindEth/juno/starknet/compiler"
9+
"github.com/NethermindEth/juno/utils"
10+
"github.com/starknet-io/starknet-p2pspecs/p2p/proto/class"
11+
)
12+
13+
func AdaptClass(cls *class.Cairo1Class) core.Class {
14+
if cls == nil {
15+
return nil
16+
}
17+
18+
abiHash := crypto.StarknetKeccak([]byte(cls.Abi))
19+
20+
program := utils.Map(cls.Program, AdaptFelt)
21+
compiled, err := createCompiledClass(cls)
22+
if err != nil {
23+
panic(err)
24+
}
25+
26+
adaptEP := func(points []*class.SierraEntryPoint) []core.SierraEntryPoint {
27+
// usage of NonNilSlice is essential because relevant core class fields are non nil
28+
return utils.Map(utils.NonNilSlice(points), adaptSierra)
29+
}
30+
31+
entryPoints := cls.EntryPoints
32+
return &core.Cairo1Class{
33+
Abi: cls.Abi,
34+
AbiHash: abiHash,
35+
EntryPoints: struct {
36+
Constructor []core.SierraEntryPoint
37+
External []core.SierraEntryPoint
38+
L1Handler []core.SierraEntryPoint
39+
}{
40+
Constructor: adaptEP(entryPoints.Constructors),
41+
External: adaptEP(entryPoints.Externals),
42+
L1Handler: adaptEP(entryPoints.L1Handlers),
43+
},
44+
Program: program,
45+
ProgramHash: crypto.PoseidonArray(program...),
46+
SemanticVersion: cls.ContractClassVersion,
47+
Compiled: compiled,
48+
}
49+
}
50+
51+
func adaptSierra(e *class.SierraEntryPoint) core.SierraEntryPoint {
52+
return core.SierraEntryPoint{
53+
Index: e.Index,
54+
Selector: AdaptFelt(e.Selector),
55+
}
56+
}
57+
58+
func createCompiledClass(cairo1 *class.Cairo1Class) (*core.CompiledClass, error) {
59+
if cairo1 == nil {
60+
return nil, nil
61+
}
62+
63+
adapt := func(ep *class.SierraEntryPoint) starknet.SierraEntryPoint {
64+
return starknet.SierraEntryPoint{
65+
Index: ep.Index,
66+
Selector: AdaptFelt(ep.Selector),
67+
}
68+
}
69+
ep := cairo1.EntryPoints
70+
def := &starknet.SierraDefinition{
71+
Abi: cairo1.Abi,
72+
EntryPoints: starknet.SierraEntryPoints{
73+
// WARNING: usage of utils.NonNilSlice is essential, otherwise compilation will finish with errors
74+
// todo move NonNilSlice to Compile ?
75+
Constructor: utils.Map(utils.NonNilSlice(ep.Constructors), adapt),
76+
External: utils.Map(utils.NonNilSlice(ep.Externals), adapt),
77+
L1Handler: utils.Map(utils.NonNilSlice(ep.L1Handlers), adapt),
78+
},
79+
Program: utils.Map(cairo1.Program, AdaptFelt),
80+
Version: cairo1.ContractClassVersion,
81+
}
82+
83+
compiledClass, err := compiler.Compile(def)
84+
if err != nil {
85+
return nil, err
86+
}
87+
88+
return sn2core.AdaptCompiledClass(compiledClass)
89+
}

‎adapters/p2p2consensus/felt.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package p2p2consensus
2+
3+
import (
4+
"encoding/binary"
5+
6+
"github.com/NethermindEth/juno/core/felt"
7+
"github.com/NethermindEth/juno/utils"
8+
ethcommon "github.com/ethereum/go-ethereum/common"
9+
"github.com/starknet-io/starknet-p2pspecs/p2p/proto/common"
10+
"github.com/starknet-io/starknet-p2pspecs/p2p/proto/sync/receipt"
11+
)
12+
13+
func AdaptHash(h *common.Hash) *felt.Felt {
14+
return adapt(h)
15+
}
16+
17+
func AdaptAddress(h *common.Address) *felt.Felt {
18+
return adapt(h)
19+
}
20+
21+
func AdaptEthAddress(h *receipt.EthereumAddress) ethcommon.Address {
22+
return ethcommon.BytesToAddress(h.Elements)
23+
}
24+
25+
func AdaptFelt(f *common.Felt252) *felt.Felt {
26+
return adapt(f)
27+
}
28+
29+
func adapt(v interface{ GetElements() []byte }) *felt.Felt {
30+
if utils.IsNil(v) {
31+
return nil
32+
}
33+
34+
return new(felt.Felt).SetBytes(v.GetElements())
35+
}
36+
37+
func AdaptUint128(u *common.Uint128) *felt.Felt {
38+
if u == nil {
39+
return nil
40+
}
41+
42+
bytes := make([]byte, 16) //nolint:mnd
43+
44+
binary.BigEndian.PutUint64(bytes[:8], u.High)
45+
binary.BigEndian.PutUint64(bytes[8:], u.Low)
46+
47+
return new(felt.Felt).SetBytes(bytes)
48+
}

‎adapters/p2p2consensus/proposal.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package p2p2consensus
2+
3+
import (
4+
"math/big"
5+
6+
"github.com/Masterminds/semver/v3"
7+
consensus "github.com/NethermindEth/juno/consensus/types"
8+
"github.com/NethermindEth/juno/core"
9+
"github.com/NethermindEth/juno/core/felt"
10+
p2pconsensus "github.com/NethermindEth/juno/p2p/proto/consensus/consensus"
11+
"github.com/NethermindEth/juno/utils"
12+
common "github.com/starknet-io/starknet-p2pspecs/p2p/proto/common"
13+
)
14+
15+
func U128ToFelt(u *common.Uint128) *felt.Felt {
16+
lowBig := new(big.Int).SetUint64(u.Low)
17+
highBig := new(big.Int).SetUint64(u.High)
18+
highBig.Lsh(highBig, 64) //nolint:mnd
19+
return new(felt.Felt).SetBigInt(highBig.Or(highBig, lowBig))
20+
}
21+
22+
func AdaptProposalInit(msg *p2pconsensus.ProposalInit) consensus.ProposalInit {
23+
return consensus.ProposalInit{
24+
BlockNum: msg.BlockNumber,
25+
Proposer: *new(felt.Felt).SetBytes(msg.Proposer.Elements),
26+
}
27+
}
28+
29+
func AdaptBlockInfo(msg *p2pconsensus.BlockInfo) *consensus.BlockInfo {
30+
return &consensus.BlockInfo{
31+
BlockNumber: msg.BlockNumber,
32+
Builder: *new(felt.Felt).SetBytes(msg.Builder.Elements),
33+
Timestamp: msg.Timestamp,
34+
L2GasPriceFRI: *U128ToFelt(msg.L2GasPriceFri),
35+
L1GasPriceWEI: *U128ToFelt(msg.L1DataGasPriceWei),
36+
L1DataGasPriceWEI: *U128ToFelt(msg.L1DataGasPriceWei),
37+
EthToStrkRate: *U128ToFelt(msg.EthToStrkRate),
38+
L1DAMode: core.L1DAMode(msg.L1DaMode),
39+
}
40+
}
41+
42+
func AdaptProposalCommitment(msg *p2pconsensus.ProposalCommitment) consensus.ProposalCommitment {
43+
return consensus.ProposalCommitment{
44+
BlockNumber: msg.BlockNumber,
45+
Builder: *new(felt.Felt).SetBytes(msg.Builder.Elements),
46+
47+
ParentCommitment: *new(felt.Felt).SetBytes(msg.ParentCommitment.Elements),
48+
Timestamp: msg.Timestamp,
49+
ProtocolVersion: *semver.MustParse(msg.ProtocolVersion),
50+
51+
OldStateRoot: *new(felt.Felt).SetBytes(msg.OldStateRoot.Elements),
52+
VersionConstantCommitment: *new(felt.Felt).SetBytes(msg.VersionConstantCommitment.Elements),
53+
NextL2GasPriceFRI: *U128ToFelt(msg.NextL2GasPriceFri),
54+
55+
StateDiffCommitment: *new(felt.Felt).SetBytes(msg.StateDiffCommitment.Elements),
56+
TransactionCommitment: *new(felt.Felt).SetBytes(msg.TransactionCommitment.Elements),
57+
EventCommitment: *new(felt.Felt).SetBytes(msg.EventCommitment.Elements),
58+
ReceiptCommitment: *new(felt.Felt).SetBytes(msg.ReceiptCommitment.Elements),
59+
ConcatenatedCounts: *new(felt.Felt).SetBytes(msg.ConcatenatedCounts.Elements),
60+
L1GasPriceFRI: *U128ToFelt(msg.L1GasPriceFri),
61+
L1DataGasPriceFRI: *U128ToFelt(msg.L1DataGasPriceFri),
62+
L2GasPriceFRI: *U128ToFelt(msg.L2GasPriceFri),
63+
L2GasUsed: *U128ToFelt(msg.L2GasUsed),
64+
L1DAMode: core.L1DAMode(msg.L1DaMode),
65+
}
66+
}
67+
68+
func AdaptProposalTransaction(msg *p2pconsensus.TransactionBatch, network *utils.Network) []consensus.Transaction {
69+
txns := make([]consensus.Transaction, len(msg.Transactions))
70+
for i := range msg.Transactions {
71+
txn, class := AdaptTransaction(msg.Transactions[i], network)
72+
txns[i] = consensus.Transaction{
73+
Transaction: txn,
74+
Class: class,
75+
PaidFeeOnL1: nil, // Todo: this value is not passed in the spec.
76+
}
77+
}
78+
return txns
79+
}
80+
81+
func AdaptProposalFin(msg *p2pconsensus.ProposalFin) consensus.ProposalFin {
82+
return consensus.ProposalFin(*new(felt.Felt).SetBytes(msg.ProposalCommitment.Elements))
83+
}

‎adapters/p2p2consensus/transaction.go

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package p2p2consensus
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/NethermindEth/juno/core"
7+
"github.com/NethermindEth/juno/core/felt"
8+
p2pconsensus "github.com/NethermindEth/juno/p2p/proto/consensus/consensus"
9+
"github.com/NethermindEth/juno/utils"
10+
"github.com/starknet-io/starknet-p2pspecs/p2p/proto/common"
11+
"github.com/starknet-io/starknet-p2pspecs/p2p/proto/transaction"
12+
)
13+
14+
//nolint:funlen
15+
func AdaptTransaction(t *p2pconsensus.ConsensusTransaction, network *utils.Network) (core.Transaction, core.Class) {
16+
if t == nil {
17+
return nil, nil
18+
}
19+
20+
switch t.Txn.(type) {
21+
case *p2pconsensus.ConsensusTransaction_DeclareV3:
22+
tx := t.GetDeclareV3()
23+
24+
nDAMode, err := adaptVolitionDomain(tx.Common.NonceDataAvailabilityMode)
25+
if err != nil {
26+
panic(fmt.Sprintf("Failed to convert Nonce DA mode: %v to uint32", tx.Common.NonceDataAvailabilityMode))
27+
}
28+
29+
fDAMode, err := adaptVolitionDomain(tx.Common.FeeDataAvailabilityMode)
30+
if err != nil {
31+
panic(fmt.Sprintf("Failed to convert Fee DA mode: %v to uint32", tx.Common.FeeDataAvailabilityMode))
32+
}
33+
34+
class := AdaptClass(tx.Class)
35+
classHash, err := class.Hash()
36+
if err != nil {
37+
panic(err)
38+
}
39+
declareTx := &core.DeclareTransaction{
40+
TransactionHash: AdaptHash(t.TransactionHash),
41+
ClassHash: classHash,
42+
SenderAddress: AdaptAddress(tx.Common.Sender),
43+
MaxFee: nil, // in 3 version this field was removed
44+
TransactionSignature: adaptAccountSignature(tx.Common.Signature),
45+
Nonce: AdaptFelt(tx.Common.Nonce),
46+
Version: txVersion(3),
47+
CompiledClassHash: AdaptHash(tx.Common.CompiledClassHash),
48+
Tip: tx.Common.Tip,
49+
ResourceBounds: map[core.Resource]core.ResourceBounds{
50+
core.ResourceL1Gas: adaptResourceLimits(tx.Common.ResourceBounds.L1Gas),
51+
core.ResourceL2Gas: adaptResourceLimits(tx.Common.ResourceBounds.L2Gas),
52+
core.ResourceL1DataGas: adaptResourceLimits(tx.Common.ResourceBounds.L1DataGas),
53+
},
54+
PaymasterData: utils.Map(tx.Common.PaymasterData, AdaptFelt),
55+
AccountDeploymentData: utils.Map(tx.Common.AccountDeploymentData, AdaptFelt),
56+
NonceDAMode: nDAMode,
57+
FeeDAMode: fDAMode,
58+
}
59+
60+
return declareTx, class
61+
case *p2pconsensus.ConsensusTransaction_DeployAccountV3:
62+
tx := t.GetDeployAccountV3()
63+
64+
nDAMode, err := adaptVolitionDomain(tx.NonceDataAvailabilityMode)
65+
if err != nil {
66+
panic(fmt.Sprintf("Failed to convert Nonce DA mode: %v to uint32", tx.NonceDataAvailabilityMode))
67+
}
68+
69+
fDAMode, err := adaptVolitionDomain(tx.FeeDataAvailabilityMode)
70+
if err != nil {
71+
panic(fmt.Sprintf("Failed to convert Fee DA mode: %v to uint32", tx.FeeDataAvailabilityMode))
72+
}
73+
74+
addressSalt := AdaptFelt(tx.AddressSalt)
75+
classHash := AdaptHash(tx.ClassHash)
76+
callData := utils.Map(tx.Calldata, AdaptFelt)
77+
deployAccTx := &core.DeployAccountTransaction{
78+
DeployTransaction: core.DeployTransaction{
79+
TransactionHash: AdaptHash(t.TransactionHash),
80+
ContractAddressSalt: addressSalt,
81+
ContractAddress: core.ContractAddress(&felt.Zero, classHash, addressSalt, callData),
82+
ClassHash: classHash,
83+
ConstructorCallData: callData,
84+
Version: txVersion(3),
85+
},
86+
MaxFee: nil, // todo(kirill) update spec? missing field
87+
TransactionSignature: adaptAccountSignature(tx.Signature),
88+
Nonce: AdaptFelt(tx.Nonce),
89+
Tip: tx.Tip,
90+
ResourceBounds: map[core.Resource]core.ResourceBounds{
91+
core.ResourceL1Gas: adaptResourceLimits(tx.ResourceBounds.L1Gas),
92+
core.ResourceL2Gas: adaptResourceLimits(tx.ResourceBounds.L2Gas),
93+
core.ResourceL1DataGas: adaptResourceLimits(tx.ResourceBounds.L1DataGas),
94+
},
95+
PaymasterData: utils.Map(tx.PaymasterData, AdaptFelt),
96+
NonceDAMode: nDAMode,
97+
FeeDAMode: fDAMode,
98+
}
99+
100+
return deployAccTx, nil
101+
case *p2pconsensus.ConsensusTransaction_InvokeV3:
102+
tx := t.GetInvokeV3()
103+
104+
nDAMode, err := adaptVolitionDomain(tx.NonceDataAvailabilityMode)
105+
if err != nil {
106+
panic(fmt.Sprintf("Failed to convert Nonce DA mode: %v to uint32", tx.NonceDataAvailabilityMode))
107+
}
108+
109+
fDAMode, err := adaptVolitionDomain(tx.FeeDataAvailabilityMode)
110+
if err != nil {
111+
panic(fmt.Sprintf("Failed to convert Fee DA mode: %v to uint32", tx.FeeDataAvailabilityMode))
112+
}
113+
114+
invTx := &core.InvokeTransaction{
115+
TransactionHash: AdaptHash(t.TransactionHash),
116+
ContractAddress: nil, // todo call core.ContractAddress() ?
117+
CallData: utils.Map(tx.Calldata, AdaptFelt),
118+
TransactionSignature: adaptAccountSignature(tx.Signature),
119+
MaxFee: nil, // in 3 version this field was removed
120+
Version: txVersion(3),
121+
Nonce: AdaptFelt(tx.Nonce),
122+
SenderAddress: AdaptAddress(tx.Sender),
123+
EntryPointSelector: nil,
124+
Tip: tx.Tip,
125+
ResourceBounds: map[core.Resource]core.ResourceBounds{
126+
core.ResourceL1Gas: adaptResourceLimits(tx.ResourceBounds.L1Gas),
127+
core.ResourceL2Gas: adaptResourceLimits(tx.ResourceBounds.L2Gas),
128+
core.ResourceL1DataGas: adaptResourceLimits(tx.ResourceBounds.L1DataGas),
129+
},
130+
PaymasterData: utils.Map(tx.PaymasterData, AdaptFelt),
131+
NonceDAMode: nDAMode,
132+
FeeDAMode: fDAMode,
133+
AccountDeploymentData: nil,
134+
}
135+
136+
return invTx, nil
137+
case *p2pconsensus.ConsensusTransaction_L1Handler:
138+
tx := t.GetL1Handler()
139+
l1Tx := &core.L1HandlerTransaction{
140+
TransactionHash: AdaptHash(t.TransactionHash),
141+
ContractAddress: AdaptAddress(tx.Address),
142+
EntryPointSelector: AdaptFelt(tx.EntryPointSelector),
143+
Nonce: AdaptFelt(tx.Nonce),
144+
CallData: utils.Map(tx.Calldata, AdaptFelt),
145+
Version: txVersion(0),
146+
}
147+
148+
return l1Tx, nil
149+
default:
150+
panic(fmt.Errorf("unsupported tx type %T", t.Txn))
151+
}
152+
}
153+
154+
func adaptResourceLimits(limits *transaction.ResourceLimits) core.ResourceBounds {
155+
return core.ResourceBounds{
156+
MaxAmount: AdaptFelt(limits.MaxAmount).Uint64(),
157+
MaxPricePerUnit: AdaptFelt(limits.MaxPricePerUnit),
158+
}
159+
}
160+
161+
func adaptAccountSignature(s *transaction.AccountSignature) []*felt.Felt {
162+
return utils.Map(s.Parts, AdaptFelt)
163+
}
164+
165+
func txVersion(v uint64) *core.TransactionVersion {
166+
return new(core.TransactionVersion).SetUint64(v)
167+
}
168+
169+
func adaptVolitionDomain(v common.VolitionDomain) (core.DataAvailabilityMode, error) {
170+
switch v {
171+
case common.VolitionDomain_L1:
172+
return core.DAModeL1, nil
173+
case common.VolitionDomain_L2:
174+
return core.DAModeL2, nil
175+
default:
176+
return 0, fmt.Errorf("unknown volition domain %d", v)
177+
}
178+
}

‎consensus/types/proposal.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package types
2+
3+
import (
4+
"github.com/Masterminds/semver/v3"
5+
"github.com/NethermindEth/juno/core"
6+
"github.com/NethermindEth/juno/core/felt"
7+
)
8+
9+
type Transaction struct {
10+
Transaction core.Transaction
11+
Class core.Class
12+
PaidFeeOnL1 *felt.Felt
13+
}
14+
15+
type ProposalFin felt.Felt
16+
17+
type ValueID felt.Felt
18+
19+
type BlockInfo struct {
20+
BlockNumber uint64
21+
Builder felt.Felt
22+
Timestamp uint64
23+
L2GasPriceFRI felt.Felt
24+
L1GasPriceWEI felt.Felt
25+
L1DataGasPriceWEI felt.Felt
26+
EthToStrkRate felt.Felt
27+
L1DAMode core.L1DAMode
28+
}
29+
30+
type ProposalInit struct {
31+
BlockNum uint64
32+
Proposer felt.Felt
33+
}
34+
35+
type ProposalCommitment struct {
36+
BlockNumber uint64
37+
Builder felt.Felt
38+
39+
// We must set these by hand. They will be compared against ProposalCommitment
40+
ParentCommitment felt.Felt
41+
Timestamp uint64
42+
ProtocolVersion semver.Version
43+
44+
// These also need set by hand. However, we would need to update the DB
45+
// and blockchain Reader interface, so they are ignored for now.
46+
OldStateRoot felt.Felt
47+
VersionConstantCommitment felt.Felt
48+
NextL2GasPriceFRI felt.Felt // If empty proposal, use last value
49+
50+
// These values may be zero for empty proposals
51+
StateDiffCommitment felt.Felt
52+
TransactionCommitment felt.Felt
53+
EventCommitment felt.Felt
54+
ReceiptCommitment felt.Felt
55+
ConcatenatedCounts felt.Felt
56+
L1GasPriceFRI felt.Felt
57+
L1DataGasPriceFRI felt.Felt
58+
L2GasPriceFRI felt.Felt
59+
L2GasUsed felt.Felt
60+
L1DAMode core.L1DAMode
61+
}

0 commit comments

Comments
 (0)
Please sign in to comment.