gecko/vms/timestampvm/service.go

103 lines
2.9 KiB
Go

// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package timestampvm
import (
"errors"
"net/http"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/utils/formatting"
)
var (
errDBError = errors.New("error getting data from database")
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 {
byteFormatter := formatting.CB58{}
if err := byteFormatter.FromString(args.Data); err != nil {
return errBadData
}
dataSlice := byteFormatter.Bytes
if len(dataSlice) != dataLen {
return errBadData
}
var data [dataLen]byte // The data as an array of bytes
copy(data[:], dataSlice[: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 int64 `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 = s.vm.LastAccepted()
} 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 errDatabase
}
block, ok := blockInterface.(*Block)
if !ok {
return errBadData
}
reply.APIBlock.ID = block.ID().String()
reply.APIBlock.Timestamp = block.Timestamp
reply.APIBlock.ParentID = block.ParentID().String()
byteFormatter := formatting.CB58{Bytes: block.Data[:]}
reply.Data = byteFormatter.String()
return nil
}