Skip to content

Commit

Permalink
Add support for reading DeviceTickets V2
Browse files Browse the repository at this point in the history
  • Loading branch information
dominicletz committed Jul 8, 2024
1 parent 47b9926 commit 7a7e52a
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 24 deletions.
8 changes: 7 additions & 1 deletion edge/device_ticket.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var (

// DeviceTicket struct for connection and transmission
type DeviceTicket struct {
Version uint64
ServerID Address
BlockNumber uint64
BlockHash []byte
Expand All @@ -30,10 +31,15 @@ type DeviceTicket struct {
LocalAddr []byte
DeviceSig []byte
ServerSig []byte
Err error

// Version two fields
ChainID uint64
Epoch uint64

// Extra fields
CacheTime time.Time
deviceAddress *util.Address
Err error
}

// ValidateValues checks length of byte[] arrays and returns an error message
Expand Down
34 changes: 12 additions & 22 deletions edge/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,29 +230,19 @@ func parseDeviceTicketResponse(buffer []byte) (interface{}, error) {

func parseDeviceObjectResponse(buffer []byte) (interface{}, error) {
var response objectResponse
var responseV2 objectResponseV2
decodeStream := rlp.NewStream(bytes.NewReader(buffer), 0)
err := decodeStream.Decode(&response)
if err != nil {
// TODO: Fix this to return proper nil/not found result when the response object is just ""
// Currently it just crashes in that case with "rlp: expected input list for struct { Location string; ServerID []uint8; PeakBlock uint64; FleetAddr []uint8; TotalConnections uint64; TotalBytes uint64; LocalAddr []uint8; DeviceSig []uint8; ServerSig []uint8 }, decoding into (edge.objectResponse).Payload.Ticket"
return nil, fmt.Errorf("failed decoding or empty device response")
}
serverID := [20]byte{}
copy(serverID[:], response.Payload.Ticket.ServerID)
fleetAddr := [20]byte{}
copy(fleetAddr[:], response.Payload.Ticket.FleetAddr)
deviceObj := &DeviceTicket{
ServerID: serverID,
BlockNumber: response.Payload.Ticket.PeakBlock,
BlockHash: nil,
FleetAddr: fleetAddr,
TotalConnections: response.Payload.Ticket.TotalConnections,
TotalBytes: response.Payload.Ticket.TotalBytes,
DeviceSig: response.Payload.Ticket.DeviceSig,
ServerSig: response.Payload.Ticket.ServerSig,
LocalAddr: response.Payload.Ticket.LocalAddr,
}
return deviceObj, nil

if err := decodeStream.Decode(&response); err != nil {
decodeStream.Reset(bytes.NewReader(buffer), 0)
if err2 := decodeStream.Decode(&responseV2); err2 != nil {
return nil, fmt.Errorf("failed decoding or empty device response: %w & %w", err, err2)
} else {
return responseV2.makeDeviceTicket(), nil
}
}

return response.makeDeviceTicket(), nil
}

// TODO: decode merkle tree from message
Expand Down
57 changes: 57 additions & 0 deletions edge/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,25 @@ type objectResponse struct {
}
}

type objectResponseV2 struct {
RequestID uint64
Payload struct {
Type string
Ticket struct {
Location string // should be "location"
ServerID []byte
ChainID uint64
Epoch uint64
FleetAddr []byte
TotalConnections uint64
TotalBytes uint64
LocalAddr []byte
DeviceSig []byte
ServerSig []byte
}
}
}

type serverObjectResponse struct {
RequestID uint64
Payload struct {
Expand Down Expand Up @@ -218,3 +237,41 @@ func findItemInItems(items interface{}, key string) (item Item, err error) {
err = errKeyNotFoundInItems
return
}

func (response *objectResponse) makeDeviceTicket() *DeviceTicket {
serverID := [20]byte{}
copy(serverID[:], response.Payload.Ticket.ServerID)
fleetAddr := [20]byte{}
copy(fleetAddr[:], response.Payload.Ticket.FleetAddr)
return &DeviceTicket{
Version: 1,
ServerID: serverID,
BlockNumber: response.Payload.Ticket.PeakBlock,
BlockHash: nil,
FleetAddr: fleetAddr,
TotalConnections: response.Payload.Ticket.TotalConnections,
TotalBytes: response.Payload.Ticket.TotalBytes,
DeviceSig: response.Payload.Ticket.DeviceSig,
ServerSig: response.Payload.Ticket.ServerSig,
LocalAddr: response.Payload.Ticket.LocalAddr,
}
}

func (response *objectResponseV2) makeDeviceTicket() *DeviceTicket {
serverID := [20]byte{}
copy(serverID[:], response.Payload.Ticket.ServerID)
fleetAddr := [20]byte{}
copy(fleetAddr[:], response.Payload.Ticket.FleetAddr)
return &DeviceTicket{
Version: 2,
ServerID: serverID,
ChainID: response.Payload.Ticket.ChainID,
Epoch: response.Payload.Ticket.Epoch,
FleetAddr: fleetAddr,
TotalConnections: response.Payload.Ticket.TotalConnections,
TotalBytes: response.Payload.Ticket.TotalBytes,
DeviceSig: response.Payload.Ticket.DeviceSig,
ServerSig: response.Payload.Ticket.ServerSig,
LocalAddr: response.Payload.Ticket.LocalAddr,
}
}
9 changes: 9 additions & 0 deletions rpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,15 @@ func (client *Client) CheckTicket() {
func (client *Client) isRecentTicket(tck *edge.DeviceTicket) bool {
lvbn, _ := client.LastValid()

if tck.Version == 2 {
header := client.GetBlockHeaderValid(lvbn)
if header.Number() == 0 {
return false
}
epoch := uint64(header.Timestamp()) / 2_592_000
return tck.Epoch >= epoch
}

if tck == nil {
return false
}
Expand Down
2 changes: 1 addition & 1 deletion rpc/socks.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ func (socksServer *Server) doConnectDevice(requestId int64, deviceName string, p
if err != nil {
// Errors are fatal such as 'deviceName' is not an address
// or 'deviceName' is not on the allow list. In latter case caching
// might delay the time until an allowance reckognized
// might delay the time until an allowance recognized
return nil, err
}

Expand Down

0 comments on commit 7a7e52a

Please sign in to comment.