2019-11-28 16:06:09 +00:00
|
|
|
package state
|
2018-04-16 20:15:30 +00:00
|
|
|
|
|
|
|
import (
|
2020-06-09 09:12:56 +00:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
|
2020-03-03 14:21:42 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
2020-06-09 09:12:56 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
2020-03-03 14:21:42 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2018-04-16 20:15:30 +00:00
|
|
|
)
|
|
|
|
|
2019-11-28 16:06:09 +00:00
|
|
|
// Contract holds information about a smart contract in the NEO blockchain.
|
|
|
|
type Contract struct {
|
2020-06-09 09:12:56 +00:00
|
|
|
ID int32
|
|
|
|
Script []byte
|
|
|
|
Manifest manifest.Manifest
|
2018-04-16 20:15:30 +00:00
|
|
|
|
|
|
|
scriptHash util.Uint160
|
|
|
|
}
|
2019-09-30 16:52:16 +00:00
|
|
|
|
|
|
|
// DecodeBinary implements Serializable interface.
|
2019-11-28 16:06:09 +00:00
|
|
|
func (cs *Contract) DecodeBinary(br *io.BinReader) {
|
2020-06-09 09:12:56 +00:00
|
|
|
cs.ID = int32(br.ReadU32LE())
|
2019-12-06 15:37:37 +00:00
|
|
|
cs.Script = br.ReadVarBytes()
|
2020-06-09 09:12:56 +00:00
|
|
|
cs.Manifest.DecodeBinary(br)
|
2019-10-11 15:21:34 +00:00
|
|
|
cs.createHash()
|
2019-09-30 16:52:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// EncodeBinary implements Serializable interface.
|
2019-11-28 16:06:09 +00:00
|
|
|
func (cs *Contract) EncodeBinary(bw *io.BinWriter) {
|
2020-06-09 09:12:56 +00:00
|
|
|
bw.WriteU32LE(uint32(cs.ID))
|
2019-11-22 10:34:06 +00:00
|
|
|
bw.WriteVarBytes(cs.Script)
|
2020-06-09 09:12:56 +00:00
|
|
|
cs.Manifest.EncodeBinary(bw)
|
2019-09-30 16:52:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ScriptHash returns a contract script hash.
|
2019-11-28 16:06:09 +00:00
|
|
|
func (cs *Contract) ScriptHash() util.Uint160 {
|
2019-10-11 15:21:34 +00:00
|
|
|
if cs.scriptHash.Equals(util.Uint160{}) {
|
|
|
|
cs.createHash()
|
2019-09-30 16:52:16 +00:00
|
|
|
}
|
2019-10-11 15:21:34 +00:00
|
|
|
return cs.scriptHash
|
2019-09-30 16:52:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// createHash creates contract script hash.
|
2019-11-28 16:06:09 +00:00
|
|
|
func (cs *Contract) createHash() {
|
2019-10-11 15:21:34 +00:00
|
|
|
cs.scriptHash = hash.Hash160(cs.Script)
|
2019-09-30 16:52:16 +00:00
|
|
|
}
|
2019-10-10 14:56:58 +00:00
|
|
|
|
|
|
|
// HasStorage checks whether the contract has storage property set.
|
2019-11-28 16:06:09 +00:00
|
|
|
func (cs *Contract) HasStorage() bool {
|
2020-06-09 09:12:56 +00:00
|
|
|
return (cs.Manifest.Features & smartcontract.HasStorage) != 0
|
2019-10-10 14:56:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// IsPayable checks whether the contract has payable property set.
|
2019-11-28 16:06:09 +00:00
|
|
|
func (cs *Contract) IsPayable() bool {
|
2020-06-09 09:12:56 +00:00
|
|
|
return (cs.Manifest.Features & smartcontract.IsPayable) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
type contractJSON struct {
|
|
|
|
ID int32 `json:"id"`
|
|
|
|
Script []byte `json:"script"`
|
|
|
|
Manifest *manifest.Manifest `json:"manifest"`
|
|
|
|
ScriptHash util.Uint160 `json:"hash"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON implements json.Marshaler.
|
|
|
|
func (cs *Contract) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(&contractJSON{
|
|
|
|
ID: cs.ID,
|
|
|
|
Script: cs.Script,
|
|
|
|
Manifest: &cs.Manifest,
|
|
|
|
ScriptHash: cs.ScriptHash(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler.
|
|
|
|
func (cs *Contract) UnmarshalJSON(data []byte) error {
|
|
|
|
var cj contractJSON
|
|
|
|
if err := json.Unmarshal(data, &cj); err != nil {
|
|
|
|
return err
|
|
|
|
} else if cj.Manifest == nil {
|
|
|
|
return errors.New("empty manifest")
|
|
|
|
}
|
|
|
|
cs.ID = cj.ID
|
|
|
|
cs.Script = cj.Script
|
|
|
|
cs.Manifest = *cj.Manifest
|
|
|
|
cs.createHash()
|
|
|
|
return nil
|
2019-10-10 14:56:58 +00:00
|
|
|
}
|