Skip to content

Commit 7830c4f

Browse files
authored
impl sum proof (#843)
1 parent a5c5538 commit 7830c4f

File tree

3 files changed

+106
-14
lines changed

3 files changed

+106
-14
lines changed

service/apinode/aggregator/aggregator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func Run(projectManager *project.Manager, db *apidb.DB, sequencerAddr string, in
4747
slog.Error("failed to get project config", "error", err, "project_id", pid)
4848
continue
4949
}
50-
if cfg.ProofType == "movement" {
50+
if cfg.ProofType == "movement" || cfg.ProofType == "sum" {
5151
prevTaskID := tasks[0].TaskID
5252
tasks[len(tasks)-1].PrevTaskID = prevTaskID
5353
}

service/apinode/api/http.go

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -170,19 +170,31 @@ func (s *httpServer) createTask(c *gin.Context) {
170170
var matchedPubkey *ecdsa.PublicKey
171171
var approved bool
172172
for _, r := range recovered {
173-
addr := crypto.PubkeyToAddress(*r.pubkey)
174-
slog.Debug("recovered address", "project_id", req.ProjectID, "address", addr.String())
175-
ok, err := s.db.IsDeviceApproved(req.ProjectID, addr)
176-
if err != nil {
177-
slog.Error("failed to check device permission", "error", err)
178-
c.JSON(http.StatusInternalServerError, newErrResp(errors.Wrap(err, "failed to check device permission")))
179-
return
180-
}
181-
if ok {
182-
approved = true
183-
matchedPubkey = r.pubkey
184-
sig = r.sig
185-
break
173+
if req.ProjectID == "9" {
174+
addr := crypto.PubkeyToAddress(*r.pubkey)
175+
slog.Debug("recovered address", "project_id", req.ProjectID, "address", addr.String())
176+
ok, err := s.db.IsDeviceApproved(req.ProjectID, addr)
177+
if err != nil {
178+
slog.Error("failed to check device permission", "error", err)
179+
c.JSON(http.StatusInternalServerError, newErrResp(errors.Wrap(err, "failed to check device permission")))
180+
return
181+
}
182+
if ok {
183+
approved = true
184+
matchedPubkey = r.pubkey
185+
sig = r.sig
186+
break
187+
}
188+
} else {
189+
addr := crypto.PubkeyToAddress(*r.pubkey)
190+
deviceAddr := gjson.GetBytes(req.Payload, "address").Str
191+
192+
if strings.EqualFold(addr.Hex(), deviceAddr) {
193+
approved = true
194+
matchedPubkey = r.pubkey
195+
sig = r.sig
196+
break
197+
}
186198
}
187199
}
188200
if !approved {

vm/payload.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ func loadPayload(tasks []*task.Task, projectConfig *project.Config) ([]byte, err
2020
return encodeLivenessPayload(tasks[0], projectConfig)
2121
case "movement":
2222
return encodeMovementPayload(tasks, projectConfig)
23+
case "sum":
24+
return encodeSumPayload(tasks, projectConfig)
2325
default:
2426
return tasks[0].Payload, nil
2527
}
@@ -168,3 +170,81 @@ func abs(a, b uint64) uint64 {
168170
}
169171
return b - a
170172
}
173+
174+
const SumMaxItems = 2
175+
176+
type ProofOfSumCircuit struct {
177+
PayloadHashs [SumMaxItems][32]uints.U8
178+
Timestamps [SumMaxItems]frontend.Variable
179+
Values [SumMaxItems]frontend.Variable
180+
SigBytes [SumMaxItems][64]uints.U8
181+
182+
PubBytes [SumMaxItems][65]uints.U8
183+
StartTime frontend.Variable
184+
185+
Threshold frontend.Variable `gnark:",public"`
186+
EthAddress frontend.Variable `gnark:",public"`
187+
}
188+
189+
func (circuit *ProofOfSumCircuit) Define(api frontend.API) error { return nil }
190+
191+
func encodeSumPayload(tasks []*task.Task, projectConfig *project.Config) ([]byte, error) {
192+
if len(tasks) != 1 {
193+
return nil, errors.Errorf("invalid tasks len, expect %d, get %d", 1, len(tasks))
194+
}
195+
assignment := ProofOfSumCircuit{}
196+
task := tasks[0]
197+
if task.PrevTask == nil {
198+
return nil, errors.New("sum project miss previous task")
199+
}
200+
lastPayloadHash, _, _, lastData, err := api.HashTask(
201+
&api.CreateTaskReq{
202+
Nonce: task.PrevTask.Nonce,
203+
ProjectID: task.PrevTask.ProjectID.String(),
204+
ProjectVersion: task.PrevTask.ProjectVersion,
205+
Payload: task.PrevTask.Payload,
206+
}, projectConfig)
207+
if err != nil {
208+
return nil, err
209+
}
210+
curPayloadHash, _, _, curData, err := api.HashTask(
211+
&api.CreateTaskReq{
212+
Nonce: task.Nonce,
213+
ProjectID: task.ProjectID.String(),
214+
ProjectVersion: task.ProjectVersion,
215+
Payload: task.Payload,
216+
}, projectConfig)
217+
if err != nil {
218+
return nil, err
219+
}
220+
lastTimestamp := lastData[0].(uint64)
221+
lastValue := lastData[1].(uint64)
222+
lastSig := task.PrevTask.Signature[:64]
223+
curTimestamp := curData[0].(uint64)
224+
curValue := curData[1].(uint64)
225+
curSig := task.Signature[:64]
226+
227+
assignment.PayloadHashs[0] = [32]uints.U8(uints.NewU8Array(lastPayloadHash[:]))
228+
assignment.Timestamps[0] = lastTimestamp
229+
assignment.Values[0] = lastValue
230+
assignment.SigBytes[0] = [64]uints.U8(uints.NewU8Array(lastSig[:]))
231+
assignment.PayloadHashs[1] = [32]uints.U8(uints.NewU8Array(curPayloadHash[:]))
232+
assignment.Timestamps[1] = curTimestamp
233+
assignment.Values[1] = curValue
234+
assignment.SigBytes[1] = [64]uints.U8(uints.NewU8Array(curSig[:]))
235+
assignment.PubBytes[0] = [65]uints.U8(uints.NewU8Array(task.DevicePubKey))
236+
assignment.PubBytes[1] = [65]uints.U8(uints.NewU8Array(task.DevicePubKey))
237+
assignment.Threshold = uint64(10)
238+
239+
pubkey, err := crypto.UnmarshalPubkey(task.DevicePubKey)
240+
if err != nil {
241+
return nil, errors.Wrap(err, "failed to unmarshal pubkey")
242+
}
243+
assignment.EthAddress = crypto.PubkeyToAddress(*pubkey).Big()
244+
245+
witness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField())
246+
if err != nil {
247+
return nil, err
248+
}
249+
return witness.MarshalBinary()
250+
}

0 commit comments

Comments
 (0)