Skip to content

Commit

Permalink
Change error handling to not panic when querying block info from runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
philipstanislaus authored and turbolent committed Jun 2, 2020
1 parent 9a527fb commit a968f04
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 11 deletions.
4 changes: 2 additions & 2 deletions runtime/interface.go
Expand Up @@ -65,7 +65,7 @@ type Interface interface {
// GetCurrentBlockHeight returns the current block height.
GetCurrentBlockHeight() uint64
// GetBlockAtHeight returns the block at the given height.
GetBlockAtHeight(height uint64) (hash BlockHash, timestamp int64, exists bool)
GetBlockAtHeight(height uint64) (hash BlockHash, timestamp int64, exists bool, err error)
}

type Metrics interface {
Expand Down Expand Up @@ -142,6 +142,6 @@ func (i *EmptyRuntimeInterface) GetCurrentBlockHeight() uint64 {
return 0
}

func (i *EmptyRuntimeInterface) GetBlockAtHeight(_ uint64) (hash BlockHash, timestamp int64, exists bool) {
func (i *EmptyRuntimeInterface) GetBlockAtHeight(_ uint64) (hash BlockHash, timestamp int64, exists bool, err error) {
return
}
23 changes: 17 additions & 6 deletions runtime/runtime.go
Expand Up @@ -1206,36 +1206,47 @@ func (r *interpreterRuntime) getCurrentBlockHeight(runtimeInterface Interface) (
return
}

func (r *interpreterRuntime) getBlockAtHeight(height uint64, runtimeInterface Interface) *BlockValue {
func (r *interpreterRuntime) getBlockAtHeight(height uint64, runtimeInterface Interface) (*BlockValue, error) {

var hash BlockHash
var timestamp int64
var exists bool
var err error

wrapPanic(func() {
hash, timestamp, exists = runtimeInterface.GetBlockAtHeight(height)
hash, timestamp, exists, err = runtimeInterface.GetBlockAtHeight(height)
})

if err != nil {
return nil, err
}

if !exists {
return nil
return nil, nil
}

block := NewBlockValue(height, hash, time.Unix(0, timestamp))
return &block
return &block, nil
}

func (r *interpreterRuntime) newGetCurrentBlockFunction(runtimeInterface Interface) interpreter.HostFunction {
return func(invocation interpreter.Invocation) trampoline.Trampoline {
height := r.getCurrentBlockHeight(runtimeInterface)
block := r.getBlockAtHeight(height, runtimeInterface)
block, err := r.getBlockAtHeight(height, runtimeInterface)
if err != nil {
panic(err)
}
return trampoline.Done{Result: *block}
}
}

func (r *interpreterRuntime) newGetBlockFunction(runtimeInterface Interface) interpreter.HostFunction {
return func(invocation interpreter.Invocation) trampoline.Trampoline {
height := uint64(invocation.Arguments[0].(interpreter.UInt64Value))
block := r.getBlockAtHeight(height, runtimeInterface)
block, err := r.getBlockAtHeight(height, runtimeInterface)
if err != nil {
panic(err)
}
var result interpreter.Value
if block == nil {
result = interpreter.NilValue{}
Expand Down
7 changes: 4 additions & 3 deletions runtime/runtime_test.go
Expand Up @@ -222,17 +222,18 @@ func (i *testRuntimeInterface) GetCurrentBlockHeight() uint64 {
return 1
}

func (i *testRuntimeInterface) GetBlockAtHeight(height uint64) (hash BlockHash, timestamp int64, exists bool) {
func (i *testRuntimeInterface) GetBlockAtHeight(height uint64) (hash BlockHash, timestamp int64, exists bool,
err error) {
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, height)
err = binary.Write(buf, binary.BigEndian, height)
if err != nil {
panic(err)
}

encoded := buf.Bytes()
copy(hash[stdlib.BlockIDSize-len(encoded):], encoded)

return hash, time.Unix(int64(height), 0).UnixNano(), true
return hash, time.Unix(int64(height), 0).UnixNano(), true, nil
}

func TestRuntimeImport(t *testing.T) {
Expand Down

0 comments on commit a968f04

Please sign in to comment.