github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/state/oracle.go (about)

     1  package state
     2  
     3  import (
     4  	"errors"
     5  	"math/big"
     6  	"unicode/utf8"
     7  
     8  	"github.com/nspcc-dev/neo-go/pkg/util"
     9  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    10  )
    11  
    12  // OracleRequest represents an oracle request.
    13  type OracleRequest struct {
    14  	OriginalTxID     util.Uint256
    15  	GasForResponse   uint64
    16  	URL              string
    17  	Filter           *string
    18  	CallbackContract util.Uint160
    19  	CallbackMethod   string
    20  	UserData         []byte
    21  }
    22  
    23  // ToStackItem implements stackitem.Convertible interface. It never returns an
    24  // error.
    25  func (o *OracleRequest) ToStackItem() (stackitem.Item, error) {
    26  	filter := stackitem.Item(stackitem.Null{})
    27  	if o.Filter != nil {
    28  		filter = stackitem.Make(*o.Filter)
    29  	}
    30  	return stackitem.NewArray([]stackitem.Item{
    31  		stackitem.NewByteArray(o.OriginalTxID.BytesBE()),
    32  		stackitem.NewBigInteger(new(big.Int).SetUint64(o.GasForResponse)),
    33  		stackitem.Make(o.URL),
    34  		filter,
    35  		stackitem.NewByteArray(o.CallbackContract.BytesBE()),
    36  		stackitem.Make(o.CallbackMethod),
    37  		stackitem.NewByteArray(o.UserData),
    38  	}), nil
    39  }
    40  
    41  // FromStackItem implements stackitem.Convertible interface.
    42  func (o *OracleRequest) FromStackItem(it stackitem.Item) error {
    43  	arr, ok := it.Value().([]stackitem.Item)
    44  	if !ok || len(arr) < 7 {
    45  		return errors.New("not an array of needed length")
    46  	}
    47  	bs, err := arr[0].TryBytes()
    48  	if err != nil {
    49  		return err
    50  	}
    51  	o.OriginalTxID, err = util.Uint256DecodeBytesBE(bs)
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	gas, err := arr[1].TryInteger()
    57  	if err != nil {
    58  		return err
    59  	}
    60  	o.GasForResponse = gas.Uint64()
    61  
    62  	s, isNull, ok := itemToString(arr[2])
    63  	if !ok || isNull {
    64  		return errors.New("invalid URL")
    65  	}
    66  	o.URL = s
    67  
    68  	s, isNull, ok = itemToString(arr[3])
    69  	if !ok {
    70  		return errors.New("invalid filter")
    71  	} else if !isNull {
    72  		filter := s
    73  		o.Filter = &filter
    74  	}
    75  
    76  	bs, err = arr[4].TryBytes()
    77  	if err != nil {
    78  		return err
    79  	}
    80  	o.CallbackContract, err = util.Uint160DecodeBytesBE(bs)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	o.CallbackMethod, isNull, ok = itemToString(arr[5])
    86  	if !ok || isNull {
    87  		return errors.New("invalid callback method")
    88  	}
    89  
    90  	o.UserData, err = arr[6].TryBytes()
    91  	return err
    92  }
    93  
    94  func itemToString(it stackitem.Item) (string, bool, bool) {
    95  	_, ok := it.(stackitem.Null)
    96  	if ok {
    97  		return "", true, true
    98  	}
    99  	bs, err := it.TryBytes()
   100  	if err != nil || !utf8.Valid(bs) {
   101  		return "", false, false
   102  	}
   103  	return string(bs), false, true
   104  }