@@ -2,9 +2,7 @@ package cairo
2
2
3
3
import (
4
4
"encoding/hex"
5
- "itachi/cairo/config"
6
- "net/http"
7
-
5
+ "fmt"
8
6
junostate "github.com/NethermindEth/juno/blockchain"
9
7
"github.com/NethermindEth/juno/core"
10
8
"github.com/NethermindEth/juno/core/felt"
@@ -15,10 +13,21 @@ import (
15
13
"github.com/NethermindEth/juno/utils"
16
14
"github.com/NethermindEth/juno/vm"
17
15
"github.com/ethereum/go-ethereum/common"
16
+ "github.com/ethereum/go-ethereum/crypto"
17
+ "github.com/ethereum/go-ethereum/ethclient"
18
18
"github.com/sirupsen/logrus"
19
19
"github.com/yu-org/yu/core/context"
20
20
"github.com/yu-org/yu/core/tripod"
21
21
"github.com/yu-org/yu/core/types"
22
+ . "github.com/yu-org/yu/core/types"
23
+ "github.com/yu-org/yu/utils/log"
24
+ "itachi/cairo/adapters"
25
+ "itachi/cairo/config"
26
+ "itachi/cairo/l1/contract"
27
+ snos_ouput "itachi/cairo/snos-ouput"
28
+ "math/big"
29
+ "net/http"
30
+ "os"
22
31
)
23
32
24
33
type Cairo struct {
@@ -30,6 +39,142 @@ type Cairo struct {
30
39
network utils.Network
31
40
}
32
41
42
+ func (c * Cairo ) FinalizeBlock (block * Block ) {
43
+ logrus .SetOutput (os .Stdout )
44
+
45
+ if ! c .cfg .EnableL2UpdateState {
46
+
47
+ return
48
+ }
49
+
50
+ // for PrevStateRoot, get last finalized block
51
+ compactBlock , err := c .Chain .LastFinalized ()
52
+ if err != nil {
53
+ logrus .Fatal ("get compactBlock for finalize block failed: " , err )
54
+ }
55
+
56
+ var starkReceipt * rpc.TransactionReceipt
57
+ txns := block .Txns .ToArray ()
58
+ messagesToL1 := make ([]* rpc.MsgToL1 , 0 )
59
+ for t := 0 ; t < len (txns ); t ++ {
60
+ txn := txns [t ]
61
+ receipt , _ := c .TxDB .GetReceipt (txn .TxnHash )
62
+ receiptExtraByt := receipt .Extra
63
+ err := encoder .Unmarshal (receiptExtraByt , & starkReceipt )
64
+ if err != nil {
65
+ // handle error
66
+ logrus .Fatal ("unmarshal starkReceipt failed: " , err )
67
+ } else {
68
+ messagesToL1 = append (messagesToL1 , starkReceipt .MessagesSent ... )
69
+ }
70
+ }
71
+ // Adapt
72
+ messageL2ToL1 := make ([]* adapters.MessageL2ToL1 , len (messagesToL1 ))
73
+ for idx , msg := range messagesToL1 {
74
+ messageL2ToL1 [idx ] = & adapters.MessageL2ToL1 {
75
+ From : msg .From ,
76
+ To : msg .To ,
77
+ Payload : msg .Payload ,
78
+ }
79
+ }
80
+
81
+ // todo messagesToL2 := make([]*rpc.MsgFromL1, 0)
82
+ messagesToL2 := make ([]* adapters.MessageL1ToL2 , 0 )
83
+ //for t := 0; t < len(txns); t++ {
84
+ // txn := txns[t]
85
+ //
86
+ //}
87
+
88
+ num := uint64 (block .Height )
89
+ // init StarknetOsOutput by block
90
+ snOsOutput := & snos_ouput.StarknetOsOutput {
91
+ PrevStateRoot : new (felt.Felt ).SetBytes (compactBlock .StateRoot .Bytes ()),
92
+ NewStateRoot : new (felt.Felt ).SetBytes (block .StateRoot .Bytes ()),
93
+ BlockNumber : new (felt.Felt ).SetUint64 (num ),
94
+ BlockHash : new (felt.Felt ).SetBytes (block .Hash .Bytes ()),
95
+ ConfigHash : new (felt.Felt ).SetUint64 (0 ),
96
+ KzgDA : new (felt.Felt ).SetUint64 (0 ),
97
+ MessagesToL1 : messageL2ToL1 ,
98
+ MessagesToL2 : messagesToL2 ,
99
+ }
100
+ // cairoState.UpdateStarknetOsOutput(snOsOutput)
101
+ fmt .Printf ("snOsOutput:\n %+v\n " , snOsOutput )
102
+
103
+ // 新旧状态根对比
104
+ if snOsOutput .PrevStateRoot .String () != snOsOutput .NewStateRoot .String () {
105
+ // send snOsOutput to L1 chain
106
+ c .ethCallUpdateState (c .cairoState , snOsOutput )
107
+ }
108
+
109
+ log .DoubleLineConsole .Info (fmt .Sprintf ("Cairo Tripod finalize block, height=%d, hash=%s" , block .Height , block .Hash .String ()))
110
+
111
+ }
112
+
113
+ func (c * Cairo ) ethCallUpdateState (cairoState * CairoState , snOsOutput * snos_ouput.StarknetOsOutput ) {
114
+
115
+ client , err := ethclient .Dial (c .cfg .EthRpcUrl )
116
+ if err != nil {
117
+ fmt .Println ("init client failed: " , err )
118
+ }
119
+
120
+ starknetCore , err := contract .NewStarknetCore (common .HexToAddress (c .cfg .EthCoreContractAddress ), client )
121
+ if err != nil {
122
+ fmt .Println ("init starknetCore failed: " , err )
123
+ return
124
+ }
125
+
126
+ // encode snOsOutput to []*big.Int
127
+ programOutput , err := snOsOutput .EncodeTo ()
128
+ if err != nil {
129
+ fmt .Println ("encode snOsOutput failed: " , err )
130
+ return
131
+ }
132
+
133
+ // compute onchainDataHash and onchainDataSize
134
+ onchainDataHash , onchainDataSize , err := calculateOnchainData (programOutput )
135
+ if err != nil {
136
+ fmt .Println ("calculate onchain data failed: " , err )
137
+ return
138
+ }
139
+
140
+ chainID := big .NewInt (c .cfg .ChainID )
141
+ privateKeyHex := c .cfg .EthPrivateKey
142
+ address := c .cfg .EthWalletAddress
143
+ gasLimit := c .cfg .GasLimit
144
+ auth , err := CreateAuth (client , privateKeyHex , address , gasLimit , chainID )
145
+ if err != nil {
146
+ fmt .Println ("create auth failed: " , err )
147
+ return
148
+ }
149
+
150
+ // call updateState
151
+ tx , err := starknetCore .UpdateState (auth , programOutput , onchainDataHash , onchainDataSize )
152
+ if err != nil {
153
+ fmt .Println ("call updateState failed: %s" , err )
154
+ return
155
+ }
156
+
157
+ // retrieve transaction hash and print.
158
+ txHash := tx .Hash ()
159
+ log .DoubleLineConsole .Info ("update state, tx hash: %s" , txHash .Hex ())
160
+ fmt .Println ("https://sepolia.etherscan.io/tx/" + tx .Hash ().Hex ())
161
+
162
+ }
163
+
164
+ func calculateOnchainData (programOutput []* big.Int ) (* big.Int , * big.Int , error ) {
165
+ var data []byte
166
+ for _ , output := range programOutput {
167
+ data = append (data , output .Bytes ()... )
168
+ }
169
+ onchainDataHash := crypto .Keccak256Hash (data )
170
+ onchainDataHashBig := new (big.Int ).SetBytes (onchainDataHash .Bytes ())
171
+
172
+ // compute onchainDataSize
173
+ onchainDataSize := new (big.Int ).SetInt64 (int64 (len (programOutput )))
174
+
175
+ return onchainDataHashBig , onchainDataSize , nil
176
+ }
177
+
33
178
func NewCairo (cfg * config.Config ) * Cairo {
34
179
state , err := NewCairoState (cfg )
35
180
if err != nil {
0 commit comments