Skip to content

Commit 06918c1

Browse files
committed
feat: Sync shasta fork with raiko (vibe-kanban 03860811)
taikoxyz/raiko#642 请审查这个 pull request,我们当前分支也是要实现一模一样的功能,你需要评估 raiko2 的 rust 实现和我们 go 版本的实现的差异(目前可能有部分差异),功能上请以 raiko2 当前的 pr 实现为准,为我们 gaiko 制定重构和补齐功能的计划,开始实现之前请让我 review 方案
1 parent 4a4f952 commit 06918c1

23 files changed

+1245
-1364
lines changed

internal/prover/proof.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ import (
2020
)
2121

2222
type ProofResponse struct {
23-
Proof hexutil.Bytes `json:"proof"`
24-
Quote hexutil.Bytes `json:"quote"`
25-
PublicKey hexutil.Bytes `json:"public_key"`
26-
InstanceAddress common.Address `json:"instance_address"`
27-
Input common.Hash `json:"input"`
23+
Proof hexutil.Bytes `json:"proof"`
24+
Quote hexutil.Bytes `json:"quote"`
25+
PublicKey hexutil.Bytes `json:"public_key"`
26+
InstanceAddress common.Address `json:"instance_address"`
27+
Input common.Hash `json:"input"`
28+
ExtraData *witness.ProofCarryData `json:"extra_data,omitempty"`
2829
}
2930

3031
func (p *ProofResponse) Output(w io.Writer) error {
@@ -150,6 +151,23 @@ func genOneshotProof(
150151
return err
151152
}
152153

154+
var extraData *witness.ProofCarryData
155+
if guestInput.BlockProposed().IsShasta() {
156+
transitionInput, ok := guestInput.Transition().(witness.TransitionInputData)
157+
if !ok {
158+
if ptr, ok := guestInput.Transition().(*witness.TransitionInputData); ok && ptr != nil {
159+
transitionInput = *ptr
160+
} else {
161+
return fmt.Errorf("invalid shasta transition type: %T", guestInput.Transition())
162+
}
163+
}
164+
extraData = &witness.ProofCarryData{
165+
ChainID: guestInput.ChainID(),
166+
Verifier: guestInput.ForkVerifierAddress(args.ProofType),
167+
TransitionInput: transitionInput,
168+
}
169+
}
170+
153171
sign, err := Sign(piHash.Bytes(), prevPrivKey)
154172
if err != nil {
155173
return err
@@ -167,5 +185,6 @@ func genOneshotProof(
167185
PublicKey: crypto.FromECDSAPub(&prevPrivKey.PublicKey),
168186
InstanceAddress: newInstance,
169187
Input: piHash,
188+
ExtraData: extraData,
170189
}).Output(args.ProofWriter)
171190
}

internal/prover/shasta.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,41 @@ func genShastaAggregateProof(
3535
return err
3636
}
3737
log.Info("receive input: ", "input", input)
38-
oldInstance := common.BytesToAddress(input.Proofs[0].Proof[4:24])
39-
curInstance := oldInstance
40-
transitionHashes := make([]common.Hash, 0, len(input.Proofs))
38+
if len(input.Proofs) == 0 {
39+
return fmt.Errorf("no proofs provided")
40+
}
41+
if len(input.Proofs) != len(input.ProofCarryDataVec) {
42+
return fmt.Errorf("proofs and proof_carry_data_vec length mismatch")
43+
}
44+
if !witness.ValidateShastaProofCarryDataVec(input.ProofCarryDataVec) {
45+
return fmt.Errorf("invalid shasta proof carry data")
46+
}
47+
48+
expectedInstance := common.BytesToAddress(input.Proofs[0].Proof[4:24])
49+
if expectedInstance != newInstance {
50+
return fmt.Errorf("invalid instance: %#x", expectedInstance)
51+
}
4152
var pubKey *ecdsa.PublicKey
4253
for i, proof := range input.Proofs {
54+
if proof.Input != witness.HashShastaSubproofInput(&input.ProofCarryDataVec[i]) {
55+
return fmt.Errorf("invalid shasta proof input at index %d", i)
56+
}
4357
pubKey, err = SigToPub(proof.Input.Bytes(), proof.Proof[24:])
4458
if err != nil {
4559
return err
4660
}
47-
if crypto.PubkeyToAddress(*pubKey) != curInstance {
61+
if crypto.PubkeyToAddress(*pubKey) != expectedInstance {
4862
return fmt.Errorf("invalid proof[%d]", i)
4963
}
50-
curInstance = common.BytesToAddress(proof.Proof[4:24])
51-
transitionHashes = append(transitionHashes, proof.Input)
52-
}
53-
if newInstance != curInstance {
54-
return fmt.Errorf("invalid instance: %#x", curInstance)
64+
if common.BytesToAddress(proof.Proof[4:24]) != expectedInstance {
65+
return fmt.Errorf("invalid proof[%d] instance", i)
66+
}
5567
}
5668

57-
aggHash := witness.HashShastaAggregation(transitionHashes, input.ChainID, input.VerifierAddress, newInstance)
69+
aggHash, err := witness.ShastaPCDAggregationHash(input.ProofCarryDataVec, newInstance)
70+
if err != nil {
71+
return err
72+
}
5873
sign, err := Sign(aggHash.Bytes(), prevPrivKey)
5974
if err != nil {
6075
return err

internal/witness/abi.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ package witness
22

33
import (
44
"errors"
5+
"math/big"
6+
"reflect"
7+
"strings"
58

69
"github.com/ethereum/go-ethereum/accounts/abi"
10+
"github.com/ethereum/go-ethereum/common"
711
"github.com/taikoxyz/taiko-mono/packages/taiko-client/bindings/encoding"
12+
"github.com/taikoxyz/taiko-mono/packages/taiko-client/bindings/shasta"
813
)
914

1015
var (
@@ -66,6 +71,7 @@ var (
6671
blockProposedEvent = encoding.TaikoL1ABI.Events["BlockProposed"]
6772
blockProposedV2Event = encoding.TaikoL1ABI.Events["BlockProposedV2"]
6873
anchorV3Method = encoding.TaikoAnchorABI.Methods["anchorV3"]
74+
shastaAnchorV4Method abi.Method
6975
)
7076

7177
func init() {
@@ -89,6 +95,12 @@ func init() {
8995
panic(err)
9096
}
9197
blockMetadataV2ComponentsArgs = abi.Arguments{arg}
98+
99+
shastaAnchorABI, err := abi.JSON(strings.NewReader(shasta.ShastaAnchorABI))
100+
if err != nil {
101+
panic(err)
102+
}
103+
shastaAnchorV4Method = shastaAnchorABI.Methods["anchorV4"]
92104
}
93105

94106
// ABIEncoder is an interface for solidity structs encoding
@@ -131,3 +143,106 @@ func decodeAnchorV3ArgsSignalSlots(input []byte) ([][32]byte, error) {
131143
}
132144
return signalSlots, nil
133145
}
146+
147+
func decodeShastaAnchorCheckpoint(input []byte) (*ShastaCheckpoint, error) {
148+
if shastaAnchorV4Method.Name == "" {
149+
return nil, errors.New("shasta anchor ABI not initialized")
150+
}
151+
args := map[string]any{}
152+
if err := shastaAnchorV4Method.Inputs.UnpackIntoMap(args, input); err != nil {
153+
return nil, err
154+
}
155+
156+
var param any
157+
if value, ok := args["_blockParams"]; ok {
158+
param = value
159+
} else if value, ok := args["_checkpoint"]; ok {
160+
param = value
161+
} else {
162+
return nil, errors.New("shasta anchor params not found")
163+
}
164+
165+
return shastaCheckpointFromTuple(param)
166+
}
167+
168+
func shastaCheckpointFromTuple(value any) (*ShastaCheckpoint, error) {
169+
rv := reflect.ValueOf(value)
170+
if rv.Kind() == reflect.Pointer {
171+
if rv.IsNil() {
172+
return nil, errors.New("nil shasta anchor param")
173+
}
174+
rv = rv.Elem()
175+
}
176+
if rv.Kind() != reflect.Struct {
177+
return nil, errors.New("unexpected shasta anchor param type")
178+
}
179+
180+
numberField := rv.FieldByName("AnchorBlockNumber")
181+
if !numberField.IsValid() {
182+
numberField = rv.FieldByName("BlockNumber")
183+
}
184+
hashField := rv.FieldByName("AnchorBlockHash")
185+
if !hashField.IsValid() {
186+
hashField = rv.FieldByName("BlockHash")
187+
}
188+
stateField := rv.FieldByName("AnchorStateRoot")
189+
if !stateField.IsValid() {
190+
stateField = rv.FieldByName("StateRoot")
191+
}
192+
193+
if !numberField.IsValid() || !hashField.IsValid() || !stateField.IsValid() {
194+
return nil, errors.New("invalid shasta anchor param fields")
195+
}
196+
197+
var blockNumber uint64
198+
switch v := numberField.Interface().(type) {
199+
case *big.Int:
200+
blockNumber = v.Uint64()
201+
case uint64:
202+
blockNumber = v
203+
case uint32:
204+
blockNumber = uint64(v)
205+
default:
206+
if numberField.Kind() == reflect.Uint64 {
207+
blockNumber = numberField.Uint()
208+
} else {
209+
return nil, errors.New("unsupported block number type")
210+
}
211+
}
212+
213+
blockHash, err := toCommonHash(hashField)
214+
if err != nil {
215+
return nil, err
216+
}
217+
stateRoot, err := toCommonHash(stateField)
218+
if err != nil {
219+
return nil, err
220+
}
221+
222+
return &ShastaCheckpoint{
223+
BlockNumber: blockNumber,
224+
BlockHash: blockHash,
225+
StateRoot: stateRoot,
226+
}, nil
227+
}
228+
229+
func toCommonHash(value reflect.Value) (common.Hash, error) {
230+
if !value.IsValid() {
231+
return common.Hash{}, errors.New("invalid hash value")
232+
}
233+
switch v := value.Interface().(type) {
234+
case [32]byte:
235+
return common.BytesToHash(v[:]), nil
236+
case common.Hash:
237+
return v, nil
238+
default:
239+
if value.Kind() == reflect.Array && value.Len() == 32 && value.Type().Elem().Kind() == reflect.Uint8 {
240+
var out [32]byte
241+
for i := 0; i < 32; i++ {
242+
out[i] = byte(value.Index(i).Uint())
243+
}
244+
return common.BytesToHash(out[:]), nil
245+
}
246+
return common.Hash{}, errors.New("unsupported hash type")
247+
}
248+
}

internal/witness/aggregate.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ type RawAggregationGuestInput struct {
1212
}
1313

1414
type ShastaRawAggregationGuestInput struct {
15-
Proofs []*RawProof `json:"proofs"`
16-
ChainID uint64 `json:"chain_id"`
17-
VerifierAddress common.Address `json:"verifier_address"`
15+
Proofs []*RawProof `json:"proofs"`
16+
ProofCarryDataVec []ProofCarryData `json:"proof_carry_data_vec"`
1817
}

0 commit comments

Comments
 (0)