neoneo-go/pkg/core/contract_state.go

122 lines
3.5 KiB
Go
Raw Normal View History

package core
import (
"github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/smartcontract"
"github.com/CityOfZion/neo-go/pkg/util"
)
// Contracts is a mapping between scripthash and ContractState.
type Contracts map[util.Uint160]*ContractState
// ContractState holds information about a smart contract in the NEO blockchain.
type ContractState struct {
Script []byte
ParamList []smartcontract.ParamType
ReturnType smartcontract.ParamType
Properties smartcontract.PropertyState
Name string
CodeVersion string
Author string
Email string
Description string
scriptHash util.Uint160
}
// commit flushes all contracts to the given storage.Batch.
func (a Contracts) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
for hash, contract := range a {
contract.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STContract, hash.Bytes())
b.Put(key, buf.Bytes())
buf.Reset()
}
return nil
}
// DecodeBinary implements Serializable interface.
func (a *ContractState) DecodeBinary(br *io.BinReader) {
a.Script = br.ReadBytes()
paramBytes := br.ReadBytes()
a.ParamList = make([]smartcontract.ParamType, len(paramBytes))
for k := range paramBytes {
a.ParamList[k] = smartcontract.ParamType(paramBytes[k])
}
br.ReadLE(&a.ReturnType)
br.ReadLE(&a.Properties)
a.Name = br.ReadString()
a.CodeVersion = br.ReadString()
a.Author = br.ReadString()
a.Email = br.ReadString()
a.Description = br.ReadString()
a.createHash()
}
// EncodeBinary implements Serializable interface.
func (a *ContractState) EncodeBinary(bw *io.BinWriter) {
bw.WriteBytes(a.Script)
bw.WriteVarUint(uint64(len(a.ParamList)))
for k := range a.ParamList {
bw.WriteLE(a.ParamList[k])
}
bw.WriteLE(a.ReturnType)
bw.WriteLE(a.Properties)
bw.WriteString(a.Name)
bw.WriteString(a.CodeVersion)
bw.WriteString(a.Author)
bw.WriteString(a.Email)
bw.WriteString(a.Description)
}
// putContractStateIntoStore puts given contract state into the given store.
func putContractStateIntoStore(s storage.Store, cs *ContractState) error {
buf := io.NewBufBinWriter()
cs.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STContract, cs.ScriptHash().Bytes())
return s.Put(key, buf.Bytes())
}
// deleteContractStateInStore deletes given contract state in the given store.
func deleteContractStateInStore(s storage.Store, hash util.Uint160) error {
key := storage.AppendPrefix(storage.STContract, hash.Bytes())
return s.Delete(key)
}
// ScriptHash returns a contract script hash.
func (a *ContractState) ScriptHash() util.Uint160 {
if a.scriptHash.Equals(util.Uint160{}) {
a.createHash()
}
return a.scriptHash
}
// createHash creates contract script hash.
func (a *ContractState) createHash() {
a.scriptHash = hash.Hash160(a.Script)
}
// HasStorage checks whether the contract has storage property set.
func (cs *ContractState) HasStorage() bool {
return (cs.Properties & smartcontract.HasStorage) != 0
}
// HasDynamicInvoke checks whether the contract has dynamic invoke property set.
func (cs *ContractState) HasDynamicInvoke() bool {
return (cs.Properties & smartcontract.HasDynamicInvoke) != 0
}
// IsPayable checks whether the contract has payable property set.
func (cs *ContractState) IsPayable() bool {
return (cs.Properties & smartcontract.IsPayable) != 0
}