Skip to content

Commit a8a04eb

Browse files
Merge pull request #22 from rarimo/route-v2/state
Add new route v2/state
2 parents 6b103b5 + 22853df commit a8a04eb

File tree

8 files changed

+208
-4
lines changed

8 files changed

+208
-4
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
allOf:
2+
- $ref: '#/components/schemas/StateKey'
3+
- type: object
4+
required:
5+
- attributes
6+
properties:
7+
attributes:
8+
type: object
9+
required:
10+
- signature
11+
- timestamp
12+
properties:
13+
signature:
14+
example: "0xd0bf2f6c2270874d8870a1081b67fcb0280b61db000778f159ba39c38fb2595639c2e1d81d085916ba6ec77f2bd4c4a2ae6dfbdbaf8703da7d9fe629b2e1218a00"
15+
type: string
16+
pattern: '^0x([0-9a-fA-F]+)$'
17+
description: Signature of root state signed by relayer private key, with the last byte of the signature set to 27/28.
18+
timestamp:
19+
example: "1733395652"
20+
type: integer
21+
format: int64
22+
description: Time indicates when the event was caught, a.k.a state transition timestamp
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
type: object
2+
required:
3+
- id
4+
- type
5+
properties:
6+
id:
7+
type: string
8+
type:
9+
type: string
10+
enum:
11+
- state_v2
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
get:
2+
tags:
3+
- State
4+
summary: Get signed root state V2
5+
description: |
6+
Endpoint to get transited root state.
7+
The service listens for the new `RootUpdated` event and fetches them. By request it might return any root by
8+
its block number or root hex string if none of them provided last signed root returned.
9+
Response contain signature of root signed by relayer private key, with the last byte of the signature set to 27/28.
10+
operationId: GetStateV2
11+
parameters:
12+
- in: query
13+
name: 'filter[block]'
14+
required: false
15+
description: "Block number to filter root by"
16+
example: "666"
17+
schema:
18+
type: integer
19+
format: int64
20+
- in: query
21+
name: 'filter[root]'
22+
required: false
23+
description: "Transited root in hex format stated to filter root by."
24+
example: "0x234693c352a217d95c3a0e2e7ea17a340ac1b2290e9ab573ef97c2a86b1a5a6e"
25+
schema:
26+
type: string
27+
pattern: '^0x([0-9a-fA-F]+)$'
28+
responses:
29+
200:
30+
description: Success
31+
content:
32+
application/vnd.api+json:
33+
schema:
34+
type: object
35+
required:
36+
- data
37+
properties:
38+
data:
39+
$ref: '#/components/schemas/StateV2'
40+
'400':
41+
description: Bad Request Error
42+
content:
43+
application/json:
44+
schema:
45+
$ref: '#/components/schemas/Errors'
46+
'404':
47+
description: Not Found Error
48+
content:
49+
application/json:
50+
schema:
51+
$ref: '#/components/schemas/Errors'
52+
'500':
53+
description: Internal Error
54+
content:
55+
application/json:
56+
schema:
57+
$ref: '#/components/schemas/Errors'
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package handlers
2+
3+
import (
4+
"encoding/hex"
5+
"net/http"
6+
7+
"github.com/rarimo/proof-verification-relayer/internal/data"
8+
"github.com/rarimo/proof-verification-relayer/internal/service/api/requests"
9+
"github.com/rarimo/proof-verification-relayer/resources"
10+
"gitlab.com/distributed_lab/ape"
11+
"gitlab.com/distributed_lab/ape/problems"
12+
)
13+
14+
func GetSignedStateV2(w http.ResponseWriter, r *http.Request) {
15+
req, err := requests.NewGetSignedStateRequest(r)
16+
if err != nil {
17+
Log(r).WithError(err).Error("failed to get request")
18+
ape.RenderErr(w, problems.BadRequest(err)...)
19+
return
20+
}
21+
22+
query := StateQ(r)
23+
if req.Block != nil {
24+
query = query.FilterByBlock(*req.Block)
25+
}
26+
if req.Root != nil {
27+
query = query.FilterByRoot(*req.Root)
28+
}
29+
30+
state, err := query.SortByBlockHeight(data.DESC).Get()
31+
if err != nil {
32+
Log(r).WithError(err).Error("failed to get state")
33+
ape.RenderErr(w, problems.InternalError())
34+
return
35+
}
36+
37+
if state == nil {
38+
Log(r).Error("no block found")
39+
ape.RenderErr(w, problems.NotFound())
40+
return
41+
}
42+
43+
signature, err := signState(*state, r)
44+
if err != nil {
45+
Log(r).WithError(err).Error("failed to sign state")
46+
ape.RenderErr(w, problems.InternalError())
47+
return
48+
}
49+
50+
// See more about this here:
51+
// https://eips.ethereum.org/EIPS/eip-155#:~:text=If%20block.number%20%3E%3D%20FORK_BLKNUM%20and%20v,same%20rules%20as%20it%20did%20previously.
52+
// https://dev.to/truongpx396/understanding-ethereum-ecdsa-eip-712-and-its-role-in-permit-functionality-26ll
53+
signature[64] += 27
54+
55+
ape.Render(w, resources.StateV2Response{
56+
Data: resources.StateV2{
57+
Key: resources.Key{
58+
ID: state.ID,
59+
Type: resources.STATE_V2,
60+
},
61+
Attributes: resources.StateV2Attributes{
62+
Signature: hex.EncodeToString(signature),
63+
Timestamp: int64(state.Timestamp),
64+
},
65+
},
66+
})
67+
}

internal/service/api/router.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,18 @@ func (s *service) router() chi.Router {
6464
r.Post("/transit-state", handlers.TransitState)
6565
r.Get("/state", handlers.GetSignedState)
6666
})
67-
if s.cfg.VotingV2Config().Enable {
68-
r.Route("/v2", func(r chi.Router) {
67+
r.Route("/v2", func(r chi.Router) {
68+
if s.cfg.VotingV2Config().Enable {
6969
r.Get("/count-remaining-votes/{voting_id}", handlers.VoteCountHandlers)
7070
r.Get("/is-enough/{voting_id}", handlers.IsEnoughHandler)
7171
r.Post("/vote", handlers.VoteV2)
7272
r.Post("/predict", handlers.PredictHandlers)
7373
r.Get("/proposals", handlers.ProposalsInfo)
74-
})
75-
}
74+
}
75+
76+
r.Get("/state", handlers.GetSignedStateV2)
77+
})
78+
7679
})
7780

7881
return r

resources/model_resource_type.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const (
1111
PROPOSALS ResourceType = "proposals"
1212
SEND_TRANSACTION ResourceType = "send_transaction"
1313
STATE ResourceType = "state"
14+
STATE_V2 ResourceType = "state_v2"
1415
TXS ResourceType = "txs"
1516
VOTE_COUNT ResourceType = "vote_count"
1617
IS_ENOUGH ResourceType = "is_enough"

resources/model_state_v2.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* GENERATED. Do not modify. Your changes might be overwritten!
3+
*/
4+
5+
package resources
6+
7+
type StateV2 struct {
8+
Key
9+
Attributes StateV2Attributes `json:"attributes"`
10+
}
11+
type StateV2Response struct {
12+
Data StateV2 `json:"data"`
13+
Included Included `json:"included"`
14+
}
15+
16+
type StateV2ListResponse struct {
17+
Data []StateV2 `json:"data"`
18+
Included Included `json:"included"`
19+
Links *Links `json:"links"`
20+
}
21+
22+
// MustStateV2 - returns StateV2 from include collection.
23+
// if entry with specified key does not exist - returns nil
24+
// if entry with specified key exists but type or ID mismatches - panics
25+
func (c *Included) MustStateV2(key Key) *StateV2 {
26+
var stateV2 StateV2
27+
if c.tryFindEntry(key, &stateV2) {
28+
return &stateV2
29+
}
30+
return nil
31+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* GENERATED. Do not modify. Your changes might be overwritten!
3+
*/
4+
5+
package resources
6+
7+
type StateV2Attributes struct {
8+
// Signature of root state signed by relayer private key, with the last byte of the signature set to 27/28.
9+
Signature string `json:"signature"`
10+
// Time indicates when the event was caught, a.k.a state transition timestamp
11+
Timestamp int64 `json:"timestamp"`
12+
}

0 commit comments

Comments
 (0)