vm: move Bool method to the StackItem interface

This commit is contained in:
Evgenii Stratonikov 2020-04-28 11:23:58 +03:00
parent dca257f584
commit be38798785
5 changed files with 44 additions and 37 deletions

View file

@ -222,9 +222,7 @@ func (p *Payload) Verify(scriptHash util.Uint160) bool {
return false return false
} }
res, err := v.Estack().Pop().TryBool() return v.Estack().Pop().Bool()
return err == nil && res
} }
// DecodeBinaryUnsigned reads payload from w excluding signature. // DecodeBinaryUnsigned reads payload from w excluding signature.

View file

@ -1978,11 +1978,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
} }
resEl := vm.Estack().Pop() resEl := vm.Estack().Pop()
if resEl != nil { if resEl != nil {
res, err := resEl.TryBool() if !resEl.Bool() {
if err != nil {
return err
}
if !res {
return errors.Errorf("signature check failed") return errors.Errorf("signature check failed")
} }
if useKeys { if useKeys {

View file

@ -176,6 +176,9 @@ func (c *Context) Dup() StackItem {
return c return c
} }
// Bool implements StackItem interface.
func (c *Context) Bool() bool { panic("can't convert Context to Bool") }
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (c *Context) TryBytes() ([]byte, error) { func (c *Context) TryBytes() ([]byte, error) {
return nil, errors.New("can't convert Context to ByteArray") return nil, errors.New("can't convert Context to ByteArray")

View file

@ -80,38 +80,10 @@ func (e *Element) BigInt() *big.Int {
return val return val
} }
// TryBool attempts to get the underlying value of the element as a boolean.
// Returns error if can't convert value to boolean type.
func (e *Element) TryBool() (bool, error) {
switch t := e.value.(type) {
case *BigIntegerItem:
return t.value.Int64() != 0, nil
case *BoolItem:
return t.value, nil
case *ArrayItem, *StructItem:
return true, nil
case *ByteArrayItem:
for _, b := range t.value {
if b != 0 {
return true, nil
}
}
return false, nil
case *InteropItem:
return t.value != nil, nil
default:
return false, fmt.Errorf("can't convert to bool: " + t.String())
}
}
// Bool attempts to get the underlying value of the element as a boolean. // Bool attempts to get the underlying value of the element as a boolean.
// Will panic if the assertion failed which will be caught by the VM. // Will panic if the assertion failed which will be caught by the VM.
func (e *Element) Bool() bool { func (e *Element) Bool() bool {
val, err := e.TryBool() return e.value.Bool()
if err != nil {
panic(err)
}
return val
} }
// Bytes attempts to get the underlying value of the element as a byte array. // Bytes attempts to get the underlying value of the element as a byte array.

View file

@ -20,6 +20,8 @@ type StackItem interface {
Value() interface{} Value() interface{}
// Dup duplicates current StackItem. // Dup duplicates current StackItem.
Dup() StackItem Dup() StackItem
// Bool converts StackItem to a boolean value.
Bool() bool
// TryBytes converts StackItem to a byte slice. // TryBytes converts StackItem to a byte slice.
TryBytes() ([]byte, error) TryBytes() ([]byte, error)
// TryInteger converts StackItem to an integer. // TryInteger converts StackItem to an integer.
@ -133,6 +135,9 @@ func (i *StructItem) Dup() StackItem {
return i return i
} }
// Bool implements StackItem interface.
func (i *StructItem) Bool() bool { return true }
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (i *StructItem) TryBytes() ([]byte, error) { func (i *StructItem) TryBytes() ([]byte, error) {
return nil, errors.New("can't convert Struct to ByteArray") return nil, errors.New("can't convert Struct to ByteArray")
@ -217,6 +222,9 @@ func (i NullItem) Dup() StackItem {
return i return i
} }
// Bool implements StackItem interface.
func (i NullItem) Bool() bool { return false }
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (i NullItem) TryBytes() ([]byte, error) { func (i NullItem) TryBytes() ([]byte, error) {
return nil, errors.New("can't convert Null to ByteArray") return nil, errors.New("can't convert Null to ByteArray")
@ -260,6 +268,11 @@ func (i *BigIntegerItem) Bytes() []byte {
return emit.IntToBytes(i.value) return emit.IntToBytes(i.value)
} }
// Bool implements StackItem interface.
func (i *BigIntegerItem) Bool() bool {
return i.value.Sign() != 0
}
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (i *BigIntegerItem) TryBytes() ([]byte, error) { func (i *BigIntegerItem) TryBytes() ([]byte, error) {
return i.Bytes(), nil return i.Bytes(), nil
@ -347,6 +360,9 @@ func (i *BoolItem) Dup() StackItem {
return &BoolItem{i.value} return &BoolItem{i.value}
} }
// Bool implements StackItem interface.
func (i *BoolItem) Bool() bool { return i.value }
// Bytes converts BoolItem to bytes. // Bytes converts BoolItem to bytes.
func (i *BoolItem) Bytes() []byte { func (i *BoolItem) Bytes() []byte {
if i.value { if i.value {
@ -420,6 +436,19 @@ func (i *ByteArrayItem) String() string {
return "ByteArray" return "ByteArray"
} }
// Bool implements StackItem interface.
func (i *ByteArrayItem) Bool() bool {
if len(i.value) > MaxBigIntegerSizeBits/8 {
return true
}
for _, b := range i.value {
if b != 0 {
return true
}
}
return false
}
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (i *ByteArrayItem) TryBytes() ([]byte, error) { func (i *ByteArrayItem) TryBytes() ([]byte, error) {
return i.value, nil return i.value, nil
@ -485,6 +514,9 @@ func (i *ArrayItem) String() string {
return "Array" return "Array"
} }
// Bool implements StackItem interface.
func (i *ArrayItem) Bool() bool { return true }
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (i *ArrayItem) TryBytes() ([]byte, error) { func (i *ArrayItem) TryBytes() ([]byte, error) {
return nil, errors.New("can't convert Array to ByteArray") return nil, errors.New("can't convert Array to ByteArray")
@ -553,6 +585,9 @@ func (i *MapItem) Value() interface{} {
return i.value return i.value
} }
// Bool implements StackItem interface.
func (i *MapItem) Bool() bool { return true }
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (i *MapItem) TryBytes() ([]byte, error) { func (i *MapItem) TryBytes() ([]byte, error) {
return nil, errors.New("can't convert Map to ByteArray") return nil, errors.New("can't convert Map to ByteArray")
@ -672,6 +707,9 @@ func (i *InteropItem) Dup() StackItem {
return i return i
} }
// Bool implements StackItem interface.
func (i *InteropItem) Bool() bool { return true }
// TryBytes implements StackItem interface. // TryBytes implements StackItem interface.
func (i *InteropItem) TryBytes() ([]byte, error) { func (i *InteropItem) TryBytes() ([]byte, error) {
return nil, errors.New("can't convert Interop to ByteArray") return nil, errors.New("can't convert Interop to ByteArray")