-
Notifications
You must be signed in to change notification settings - Fork 670
/
service.go
100 lines (84 loc) · 2.89 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package timestampvm
import (
"errors"
"fmt"
"net/http"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/formatting"
"github.com/ava-labs/avalanchego/utils/json"
)
var (
errBadData = errors.New("data must be base 58 repr. of 32 bytes")
errNoSuchBlock = errors.New("couldn't get block from database. Does it exist?")
)
// Service is the API service for this VM
type Service struct{ vm *VM }
// ProposeBlockArgs are the arguments to function ProposeValue
type ProposeBlockArgs struct {
// Data in the block. Must be base 58 encoding of 32 bytes.
Data string `json:"data"`
}
// ProposeBlockReply is the reply from function ProposeBlock
type ProposeBlockReply struct{ Success bool }
// ProposeBlock is an API method to propose a new block whose data is [args].Data.
// [args].Data must be a string repr. of a 32 byte array
func (s *Service) ProposeBlock(_ *http.Request, args *ProposeBlockArgs, reply *ProposeBlockReply) error {
bytes, err := formatting.Decode(formatting.CB58, args.Data)
if err != nil || len(bytes) != dataLen {
return errBadData
}
var data [dataLen]byte // The data as an array of bytes
copy(data[:], bytes[:dataLen]) // Copy the bytes in dataSlice to data
s.vm.proposeBlock(data)
reply.Success = true
return nil
}
// APIBlock is the API representation of a block
type APIBlock struct {
Timestamp json.Uint64 `json:"timestamp"` // Timestamp of most recent block
Data string `json:"data"` // Data in the most recent block. Base 58 repr. of 5 bytes.
ID string `json:"id"` // String repr. of ID of the most recent block
ParentID string `json:"parentID"` // String repr. of ID of the most recent block's parent
}
// GetBlockArgs are the arguments to GetBlock
type GetBlockArgs struct {
// ID of the block we're getting.
// If left blank, gets the latest block
ID string
}
// GetBlockReply is the reply from GetBlock
type GetBlockReply struct {
APIBlock
}
// GetBlock gets the block whose ID is [args.ID]
// If [args.ID] is empty, get the latest block
func (s *Service) GetBlock(_ *http.Request, args *GetBlockArgs, reply *GetBlockReply) error {
var id ids.ID
var err error
if args.ID == "" {
id, err = s.vm.LastAccepted()
if err != nil {
return fmt.Errorf("problem finding the last accepted ID: %s", err)
}
} else {
id, err = ids.FromString(args.ID)
if err != nil {
return errors.New("problem parsing ID")
}
}
blockInterface, err := s.vm.GetBlock(id)
if err != nil {
return errNoSuchBlock
}
block, ok := blockInterface.(*Block)
if !ok {
return errBadData
}
reply.APIBlock.ID = block.ID().String()
reply.APIBlock.Timestamp = json.Uint64(block.Timestamp)
reply.APIBlock.ParentID = block.ParentID().String()
reply.Data, err = formatting.Encode(formatting.CB58, block.Data[:])
return err
}