package state import ( "encoding/json" "errors" "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" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/util" ) // Contract holds information about a smart contract in the NEO blockchain. type Contract struct { ID int32 Script []byte Manifest manifest.Manifest scriptHash util.Uint160 } // DecodeBinary implements Serializable interface. func (cs *Contract) DecodeBinary(br *io.BinReader) { cs.ID = int32(br.ReadU32LE()) cs.Script = br.ReadVarBytes() cs.Manifest.DecodeBinary(br) cs.createHash() } // EncodeBinary implements Serializable interface. func (cs *Contract) EncodeBinary(bw *io.BinWriter) { bw.WriteU32LE(uint32(cs.ID)) bw.WriteVarBytes(cs.Script) cs.Manifest.EncodeBinary(bw) } // ScriptHash returns a contract script hash. func (cs *Contract) ScriptHash() util.Uint160 { if cs.scriptHash.Equals(util.Uint160{}) { cs.createHash() } return cs.scriptHash } // createHash creates contract script hash. func (cs *Contract) createHash() { cs.scriptHash = hash.Hash160(cs.Script) } // HasStorage checks whether the contract has storage property set. func (cs *Contract) HasStorage() bool { return (cs.Manifest.Features & smartcontract.HasStorage) != 0 } // IsPayable checks whether the contract has payable property set. func (cs *Contract) IsPayable() bool { 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 }