[#37] Use readonly context

Delete initializing of R/W context in `init()`
and start using readonly storage context in
methods where it is possible.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2021-03-09 22:15:58 +03:00 committed by Alex Vanin
parent 6cd0808627
commit 8af80e67aa
8 changed files with 149 additions and 62 deletions

View file

@ -22,12 +22,6 @@ const (
version = 1 version = 1
) )
var ctx storage.Context
func init() {
ctx = storage.GetContext()
}
// OnNEP17Payment is a callback for NEP-17 compatible native GAS and NEO contracts. // OnNEP17Payment is a callback for NEP-17 compatible native GAS and NEO contracts.
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
caller := runtime.GetCallingScriptHash() caller := runtime.GetCallingScriptHash()
@ -37,6 +31,8 @@ func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
} }
func Init(owner interop.Hash160, addrNetmap, addrProxy interop.Hash160, name string, index, total int) { func Init(owner interop.Hash160, addrNetmap, addrProxy interop.Hash160, name string, index, total int) {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -56,6 +52,8 @@ func Init(owner interop.Hash160, addrNetmap, addrProxy interop.Hash160, name str
} }
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -75,29 +73,30 @@ func Neo() int {
return neo.BalanceOf(runtime.GetExecutingScriptHash()) return neo.BalanceOf(runtime.GetExecutingScriptHash())
} }
func irList() []common.IRNode { func irList(ctx storage.Context) []common.IRNode {
return common.InnerRingListViaStorage(ctx, netmapKey) return common.InnerRingListViaStorage(ctx, netmapKey)
} }
func currentEpoch() int { func currentEpoch(ctx storage.Context) int {
netmapContractAddr := storage.Get(ctx, netmapKey).(interop.Hash160) netmapContractAddr := storage.Get(ctx, netmapKey).(interop.Hash160)
return contract.Call(netmapContractAddr, "epoch", contract.ReadOnly).(int) return contract.Call(netmapContractAddr, "epoch", contract.ReadOnly).(int)
} }
func name() string { func name(ctx storage.Context) string {
return storage.Get(ctx, nameKey).(string) return storage.Get(ctx, nameKey).(string)
} }
func index() int { func index(ctx storage.Context) int {
return storage.Get(ctx, indexKey).(int) return storage.Get(ctx, indexKey).(int)
} }
func total() int { func total(ctx storage.Context) int {
return storage.Get(ctx, totalKey).(int) return storage.Get(ctx, totalKey).(int)
} }
func checkPermission(ir []common.IRNode) bool { func checkPermission(ir []common.IRNode) bool {
index := index() // read from contract memory ctx := storage.GetReadOnlyContext()
index := index(ctx) // read from contract memory
if len(ir) <= index { if len(ir) <= index {
return false return false
@ -108,7 +107,9 @@ func checkPermission(ir []common.IRNode) bool {
} }
func Emit() bool { func Emit() bool {
innerRingKeys := irList() ctx := storage.GetReadOnlyContext()
innerRingKeys := irList(ctx)
if !checkPermission(innerRingKeys) { if !checkPermission(innerRingKeys) {
panic("invalid invoker") panic("invalid invoker")
} }
@ -144,15 +145,16 @@ func Emit() bool {
} }
func Vote(epoch int, candidates []interop.PublicKey) { func Vote(epoch int, candidates []interop.PublicKey) {
index := index() ctx := storage.GetReadOnlyContext()
name := name() index := index(ctx)
name := name(ctx)
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("invalid invoker") panic("invalid invoker")
} }
curEpoch := currentEpoch() curEpoch := currentEpoch(ctx)
if epoch != curEpoch { if epoch != curEpoch {
panic("invalid epoch") panic("invalid epoch")
} }
@ -171,7 +173,8 @@ func Vote(epoch int, candidates []interop.PublicKey) {
} }
func Name() string { func Name() string {
return name() ctx := storage.GetReadOnlyContext()
return name(ctx)
} }
func Version() int { func Version() int {

View file

@ -40,13 +40,9 @@ const (
netmapContractKey = "netmapScriptHash" netmapContractKey = "netmapScriptHash"
) )
var ctx storage.Context
func init() {
ctx = storage.GetContext()
}
func Init(owner interop.Hash160, addrNetmap interop.Hash160) { func Init(owner interop.Hash160, addrNetmap interop.Hash160) {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -62,6 +58,8 @@ func Init(owner interop.Hash160, addrNetmap interop.Hash160) {
} }
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -74,6 +72,7 @@ func Migrate(script []byte, manifest []byte) bool {
} }
func Put(rawAuditResult []byte) bool { func Put(rawAuditResult []byte) bool {
ctx := storage.GetContext()
innerRing := common.InnerRingListViaStorage(ctx, netmapContractKey) innerRing := common.InnerRingListViaStorage(ctx, netmapContractKey)
hdr := newAuditHeader(rawAuditResult) hdr := newAuditHeader(rawAuditResult)
@ -100,22 +99,27 @@ func Put(rawAuditResult []byte) bool {
} }
func Get(id []byte) []byte { func Get(id []byte) []byte {
ctx := storage.GetReadOnlyContext()
return storage.Get(ctx, id).([]byte) return storage.Get(ctx, id).([]byte)
} }
func List() [][]byte { func List() [][]byte {
ctx := storage.GetReadOnlyContext()
it := storage.Find(ctx, []byte{}, storage.KeysOnly) it := storage.Find(ctx, []byte{}, storage.KeysOnly)
return list(it) return list(it)
} }
func ListByEpoch(epoch int) [][]byte { func ListByEpoch(epoch int) [][]byte {
ctx := storage.GetReadOnlyContext()
it := storage.Find(ctx, epoch, storage.KeysOnly) it := storage.Find(ctx, epoch, storage.KeysOnly)
return list(it) return list(it)
} }
func ListByCID(epoch int, cid []byte) [][]byte { func ListByCID(epoch int, cid []byte) [][]byte {
ctx := storage.GetReadOnlyContext()
var buf interface{} = epoch var buf interface{} = epoch
prefix := append(buf.([]byte), cid...) prefix := append(buf.([]byte), cid...)
@ -125,6 +129,7 @@ func ListByCID(epoch int, cid []byte) [][]byte {
} }
func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte { func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte {
ctx := storage.GetReadOnlyContext()
hdr := auditHeader{ hdr := auditHeader{
epoch: epoch, epoch: epoch,
cid: cid, cid: cid,

View file

@ -46,7 +46,6 @@ var (
lockTransferMsg = []byte("lock assets to withdraw") lockTransferMsg = []byte("lock assets to withdraw")
unlockTransferMsg = []byte("asset lock expired") unlockTransferMsg = []byte("asset lock expired")
ctx storage.Context
token Token token Token
) )
@ -60,11 +59,12 @@ func CreateToken() Token {
} }
func init() { func init() {
ctx = storage.GetContext()
token = CreateToken() token = CreateToken()
} }
func Init(owner, addrNetmap, addrContainer interop.Hash160) { func Init(owner, addrNetmap, addrContainer interop.Hash160) {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -81,6 +81,8 @@ func Init(owner, addrNetmap, addrContainer interop.Hash160) {
} }
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -101,18 +103,23 @@ func Decimals() int {
} }
func TotalSupply() int { func TotalSupply() int {
ctx := storage.GetReadOnlyContext()
return token.getSupply(ctx) return token.getSupply(ctx)
} }
func BalanceOf(account interop.Hash160) int { func BalanceOf(account interop.Hash160) int {
ctx := storage.GetReadOnlyContext()
return token.balanceOf(ctx, account) return token.balanceOf(ctx, account)
} }
func Transfer(from, to interop.Hash160, amount int, data interface{}) bool { func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
ctx := storage.GetContext()
return token.transfer(ctx, from, to, amount, false, nil) return token.transfer(ctx, from, to, amount, false, nil)
} }
func TransferX(from, to interop.Hash160, amount int, details []byte) bool { func TransferX(from, to interop.Hash160, amount int, details []byte) bool {
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("transferX: this method must be invoked from inner ring") panic("transferX: this method must be invoked from inner ring")
@ -130,6 +137,8 @@ func TransferX(from, to interop.Hash160, amount int, details []byte) bool {
} }
func Lock(txID []byte, from, to interop.Hash160, amount, until int) bool { func Lock(txID []byte, from, to interop.Hash160, amount, until int) bool {
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("lock: this method must be invoked from inner ring") panic("lock: this method must be invoked from inner ring")
@ -155,6 +164,8 @@ func Lock(txID []byte, from, to interop.Hash160, amount, until int) bool {
} }
func NewEpoch(epochNum int) bool { func NewEpoch(epochNum int) bool {
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("epochNum: this method must be invoked from inner ring") panic("epochNum: this method must be invoked from inner ring")
@ -182,6 +193,8 @@ func NewEpoch(epochNum int) bool {
} }
func Mint(to interop.Hash160, amount int, details []byte) bool { func Mint(to interop.Hash160, amount int, details []byte) bool {
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("mint: this method must be invoked from inner ring") panic("mint: this method must be invoked from inner ring")
@ -202,6 +215,8 @@ func Mint(to interop.Hash160, amount int, details []byte) bool {
} }
func Burn(from interop.Hash160, amount int, details []byte) bool { func Burn(from interop.Hash160, amount int, details []byte) bool {
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("burn: this method must be invoked from inner ring") panic("burn: this method must be invoked from inner ring")

View file

@ -52,15 +52,11 @@ const (
var ( var (
containerFeeTransferMsg = []byte("container creation fee") containerFeeTransferMsg = []byte("container creation fee")
eACLPrefix = []byte("eACL") eACLPrefix = []byte("eACL")
ctx storage.Context
) )
func init() {
ctx = storage.GetContext()
}
func Init(owner, addrNetmap, addrBalance, addrID interop.Hash160) { func Init(owner, addrNetmap, addrBalance, addrID interop.Hash160) {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -78,6 +74,8 @@ func Init(owner, addrNetmap, addrBalance, addrID interop.Hash160) {
} }
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -90,6 +88,8 @@ func Migrate(script []byte, manifest []byte) bool {
} }
func Put(container []byte, signature interop.Signature, publicKey interop.PublicKey) bool { func Put(container []byte, signature interop.Signature, publicKey interop.PublicKey) bool {
ctx := storage.GetContext()
offset := int(container[1]) offset := int(container[1])
offset = 2 + offset + 4 // version prefix + version size + owner prefix offset = 2 + offset + 4 // version prefix + version size + owner prefix
ownerID := container[offset : offset+25] // offset + size of owner ownerID := container[offset : offset+25] // offset + size of owner
@ -144,6 +144,8 @@ func Put(container []byte, signature interop.Signature, publicKey interop.Public
} }
func Delete(containerID, signature []byte) bool { func Delete(containerID, signature []byte) bool {
ctx := storage.GetContext()
ownerID := getOwnerByID(ctx, containerID) ownerID := getOwnerByID(ctx, containerID)
if len(ownerID) == 0 { if len(ownerID) == 0 {
panic("delete: container does not exist") panic("delete: container does not exist")
@ -170,14 +172,18 @@ func Delete(containerID, signature []byte) bool {
} }
func Get(containerID []byte) []byte { func Get(containerID []byte) []byte {
ctx := storage.GetReadOnlyContext()
return storage.Get(ctx, containerID).([]byte) return storage.Get(ctx, containerID).([]byte)
} }
func Owner(containerID []byte) []byte { func Owner(containerID []byte) []byte {
ctx := storage.GetReadOnlyContext()
return getOwnerByID(ctx, containerID) return getOwnerByID(ctx, containerID)
} }
func List(owner []byte) [][]byte { func List(owner []byte) [][]byte {
ctx := storage.GetReadOnlyContext()
if len(owner) == 0 { if len(owner) == 0 {
return getAllContainers(ctx) return getAllContainers(ctx)
} }
@ -203,6 +209,8 @@ func List(owner []byte) [][]byte {
} }
func SetEACL(eACL, signature []byte) bool { func SetEACL(eACL, signature []byte) bool {
ctx := storage.GetContext()
// get container ID // get container ID
offset := int(eACL[1]) offset := int(eACL[1])
offset = 2 + offset + 4 offset = 2 + offset + 4
@ -234,6 +242,8 @@ func SetEACL(eACL, signature []byte) bool {
} }
func EACL(containerID []byte) extendedACL { func EACL(containerID []byte) extendedACL {
ctx := storage.GetReadOnlyContext()
ownerID := getOwnerByID(ctx, containerID) ownerID := getOwnerByID(ctx, containerID)
if len(ownerID) == 0 { if len(ownerID) == 0 {
panic("getEACL: container does not exists") panic("getEACL: container does not exists")
@ -263,16 +273,18 @@ func EACL(containerID []byte) extendedACL {
} }
func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.PublicKey) bool { func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.PublicKey) bool {
ctx := storage.GetContext()
if !runtime.CheckWitness(pubKey) { if !runtime.CheckWitness(pubKey) {
panic("container: invalid witness for size estimation") panic("container: invalid witness for size estimation")
} }
if !isStorageNode(pubKey) { if !isStorageNode(ctx, pubKey) {
panic("container: only storage nodes can save size estimations") panic("container: only storage nodes can save size estimations")
} }
key := estimationKey(epoch, cid) key := estimationKey(epoch, cid)
s := getContainerSizeEstimation(key, cid) s := getContainerSizeEstimation(ctx, key, cid)
// do not add estimation twice // do not add estimation twice
for i := range s.estimations { for i := range s.estimations {
@ -295,10 +307,13 @@ func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.Public
} }
func GetContainerSize(id []byte) containerSizes { func GetContainerSize(id []byte) containerSizes {
return getContainerSizeEstimation(id, nil) ctx := storage.GetReadOnlyContext()
return getContainerSizeEstimation(ctx, id, nil)
} }
func ListContainerSizes(epoch int) [][]byte { func ListContainerSizes(epoch int) [][]byte {
ctx := storage.GetReadOnlyContext()
var buf interface{} = epoch var buf interface{} = epoch
key := []byte(estimateKeyPrefix) key := []byte(estimateKeyPrefix)
@ -317,18 +332,22 @@ func ListContainerSizes(epoch int) [][]byte {
} }
func ProcessEpoch(epochNum int) { func ProcessEpoch(epochNum int) {
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("processEpoch: this method must be invoked from inner ring") panic("processEpoch: this method must be invoked from inner ring")
} }
candidates := keysToDelete(epochNum) candidates := keysToDelete(ctx, epochNum)
for _, candidate := range candidates { for _, candidate := range candidates {
storage.Delete(ctx, candidate) storage.Delete(ctx, candidate)
} }
} }
func StartContainerEstimation(epoch int) bool { func StartContainerEstimation(epoch int) bool {
ctx := storage.GetReadOnlyContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("startEstimation: only inner ring nodes can invoke this") panic("startEstimation: only inner ring nodes can invoke this")
@ -341,6 +360,8 @@ func StartContainerEstimation(epoch int) bool {
} }
func StopContainerEstimation(epoch int) bool { func StopContainerEstimation(epoch int) bool {
ctx := storage.GetReadOnlyContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("stopEstimation: only inner ring nodes can invoke this") panic("stopEstimation: only inner ring nodes can invoke this")
@ -493,7 +514,7 @@ func estimationKey(epoch int, cid []byte) []byte {
return append(result, cid...) return append(result, cid...)
} }
func getContainerSizeEstimation(key, cid []byte) containerSizes { func getContainerSizeEstimation(ctx storage.Context, key, cid []byte) containerSizes {
data := storage.Get(ctx, key) data := storage.Get(ctx, key)
if data != nil { if data != nil {
return binary.Deserialize(data.([]byte)).(containerSizes) return binary.Deserialize(data.([]byte)).(containerSizes)
@ -507,7 +528,7 @@ func getContainerSizeEstimation(key, cid []byte) containerSizes {
// isStorageNode looks into _previous_ epoch network map, because storage node // isStorageNode looks into _previous_ epoch network map, because storage node
// announce container size estimation of previous epoch. // announce container size estimation of previous epoch.
func isStorageNode(key interop.PublicKey) bool { func isStorageNode(ctx storage.Context, key interop.PublicKey) bool {
netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160) netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160)
snapshot := contract.Call(netmapContractAddr, "snapshot", contract.ReadOnly, 1).([]storageNode) snapshot := contract.Call(netmapContractAddr, "snapshot", contract.ReadOnly, 1).([]storageNode)
@ -523,7 +544,7 @@ func isStorageNode(key interop.PublicKey) bool {
return false return false
} }
func keysToDelete(epoch int) [][]byte { func keysToDelete(ctx storage.Context, epoch int) [][]byte {
results := [][]byte{} results := [][]byte{}
it := storage.Find(ctx, []byte(estimateKeyPrefix), storage.KeysOnly) it := storage.Find(ctx, []byte(estimateKeyPrefix), storage.KeysOnly)

View file

@ -76,16 +76,12 @@ const (
var ( var (
configPrefix = []byte("config") configPrefix = []byte("config")
ctx storage.Context
) )
func init() {
ctx = storage.GetContext()
}
// Init set up initial inner ring node keys. // Init set up initial inner ring node keys.
func Init(owner interop.PublicKey, args []interop.PublicKey) bool { func Init(owner interop.PublicKey, args []interop.PublicKey) bool {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -119,6 +115,8 @@ func Init(owner interop.PublicKey, args []interop.PublicKey) bool {
// Migrate updates smart contract execution script and manifest. // Migrate updates smart contract execution script and manifest.
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -132,16 +130,20 @@ func Migrate(script []byte, manifest []byte) bool {
// InnerRingList returns array of inner ring node keys. // InnerRingList returns array of inner ring node keys.
func InnerRingList() []common.IRNode { func InnerRingList() []common.IRNode {
ctx := storage.GetReadOnlyContext()
return getInnerRingNodes(ctx, innerRingKey) return getInnerRingNodes(ctx, innerRingKey)
} }
// InnerRingCandidates returns array of inner ring candidate node keys. // InnerRingCandidates returns array of inner ring candidate node keys.
func InnerRingCandidates() []common.IRNode { func InnerRingCandidates() []common.IRNode {
ctx := storage.GetReadOnlyContext()
return getInnerRingNodes(ctx, candidatesKey) return getInnerRingNodes(ctx, candidatesKey)
} }
// InnerRingCandidateRemove removes key from the list of inner ring candidates. // InnerRingCandidateRemove removes key from the list of inner ring candidates.
func InnerRingCandidateRemove(key interop.PublicKey) bool { func InnerRingCandidateRemove(key interop.PublicKey) bool {
ctx := storage.GetContext()
if !runtime.CheckWitness(key) { if !runtime.CheckWitness(key) {
panic("irCandidateRemove: you should be the owner of the public key") panic("irCandidateRemove: you should be the owner of the public key")
} }
@ -165,6 +167,8 @@ func InnerRingCandidateRemove(key interop.PublicKey) bool {
// InnerRingCandidateAdd adds key to the list of inner ring candidates. // InnerRingCandidateAdd adds key to the list of inner ring candidates.
func InnerRingCandidateAdd(key interop.PublicKey) bool { func InnerRingCandidateAdd(key interop.PublicKey) bool {
ctx := storage.GetContext()
if !runtime.CheckWitness(key) { if !runtime.CheckWitness(key) {
panic("irCandidateAdd: you should be the owner of the public key") panic("irCandidateAdd: you should be the owner of the public key")
} }
@ -268,6 +272,7 @@ func Withdraw(user []byte, amount int) bool {
// Cheque sends gas assets back to the user if they were successfully // Cheque sends gas assets back to the user if they were successfully
// locked in NeoFS balance contract. // locked in NeoFS balance contract.
func Cheque(id []byte, user interop.Hash160, amount int, lockAcc []byte) bool { func Cheque(id []byte, user interop.Hash160, amount int, lockAcc []byte) bool {
ctx := storage.GetContext()
irList := getInnerRingNodes(ctx, innerRingKey) irList := getInnerRingNodes(ctx, innerRingKey)
threshold := len(irList)/3*2 + 1 threshold := len(irList)/3*2 + 1
@ -345,6 +350,8 @@ func Unbind(user []byte, keys []interop.PublicKey) bool {
// InnerRingUpdate updates list of inner ring nodes with provided list of // InnerRingUpdate updates list of inner ring nodes with provided list of
// public keys. // public keys.
func InnerRingUpdate(chequeID []byte, args []interop.PublicKey) bool { func InnerRingUpdate(chequeID []byte, args []interop.PublicKey) bool {
ctx := storage.GetContext()
if len(args) < minInnerRingSize { if len(args) < minInnerRingSize {
panic("irUpdate: bad arguments") panic("irUpdate: bad arguments")
} }
@ -418,6 +425,8 @@ loop:
// IsInnerRing returns 'true' if key is inside of inner ring list. // IsInnerRing returns 'true' if key is inside of inner ring list.
func IsInnerRing(key []byte) bool { func IsInnerRing(key []byte) bool {
ctx := storage.GetReadOnlyContext()
if len(key) != publicKeySize { if len(key) != publicKeySize {
panic("isInnerRing: incorrect public key") panic("isInnerRing: incorrect public key")
} }
@ -436,11 +445,14 @@ func IsInnerRing(key []byte) bool {
// Config returns value of NeoFS configuration with provided key. // Config returns value of NeoFS configuration with provided key.
func Config(key []byte) interface{} { func Config(key []byte) interface{} {
ctx := storage.GetReadOnlyContext()
return getConfig(ctx, key) return getConfig(ctx, key)
} }
// SetConfig key-value pair as a NeoFS runtime configuration value. // SetConfig key-value pair as a NeoFS runtime configuration value.
func SetConfig(id, key, val []byte) bool { func SetConfig(id, key, val []byte) bool {
ctx := storage.GetContext()
// check if it is inner ring invocation // check if it is inner ring invocation
irList := getInnerRingNodes(ctx, innerRingKey) irList := getInnerRingNodes(ctx, innerRingKey)
threshold := len(irList)/3*2 + 1 threshold := len(irList)/3*2 + 1
@ -478,6 +490,8 @@ func SetConfig(id, key, val []byte) bool {
// ListConfig returns array of all key-value pairs of NeoFS configuration. // ListConfig returns array of all key-value pairs of NeoFS configuration.
func ListConfig() []record { func ListConfig() []record {
ctx := storage.GetReadOnlyContext()
var config []record var config []record
it := storage.Find(ctx, configPrefix, storage.None) it := storage.Find(ctx, configPrefix, storage.None)
@ -495,6 +509,8 @@ func ListConfig() []record {
// InitConfig set up initial NeoFS key-value configuration. // InitConfig set up initial NeoFS key-value configuration.
func InitConfig(args [][]byte) bool { func InitConfig(args [][]byte) bool {
ctx := storage.GetContext()
if getConfig(ctx, candidateFeeConfigKey) != nil { if getConfig(ctx, candidateFeeConfigKey) != nil {
panic("neofs: configuration already installed") panic("neofs: configuration already installed")
} }

View file

@ -23,13 +23,9 @@ const (
containerContractKey = "containerScriptHash" containerContractKey = "containerScriptHash"
) )
var ctx storage.Context
func init() {
ctx = storage.GetContext()
}
func Init(owner, addrNetmap, addrContainer interop.Hash160) { func Init(owner, addrNetmap, addrContainer interop.Hash160) {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -46,6 +42,8 @@ func Init(owner, addrNetmap, addrContainer interop.Hash160) {
} }
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -62,6 +60,8 @@ func AddKey(owner []byte, keys []interop.PublicKey) bool {
panic("addKey: incorrect owner") panic("addKey: incorrect owner")
} }
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("addKey: invocation from non inner ring node") panic("addKey: invocation from non inner ring node")
@ -97,6 +97,8 @@ func RemoveKey(owner []byte, keys []interop.PublicKey) bool {
panic("removeKey: incorrect owner") panic("removeKey: incorrect owner")
} }
ctx := storage.GetContext()
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("removeKey: invocation from non inner ring node") panic("removeKey: invocation from non inner ring node")
@ -134,6 +136,8 @@ func Key(owner []byte) [][]byte {
panic("key: incorrect owner") panic("key: incorrect owner")
} }
ctx := storage.GetReadOnlyContext()
info := getUserInfo(ctx, owner) info := getUserInfo(ctx, owner)
return info.Keys return info.Keys
@ -162,6 +166,8 @@ func invokeIDKeys(owner []byte, keys [][]byte, prefix []byte) []byte {
} }
func fromKnownContract(caller []byte) bool { func fromKnownContract(caller []byte) bool {
ctx := storage.GetReadOnlyContext()
containerContractAddr := storage.Get(ctx, containerContractKey).([]byte) containerContractAddr := storage.Get(ctx, containerContractKey).([]byte)
if common.BytesEqual(caller, containerContractAddr) { if common.BytesEqual(caller, containerContractAddr) {
return true return true
@ -171,5 +177,6 @@ func fromKnownContract(caller []byte) bool {
} }
func irList() []common.IRNode { func irList() []common.IRNode {
ctx := storage.GetReadOnlyContext()
return common.InnerRingListViaStorage(ctx, netmapContractKey) return common.InnerRingListViaStorage(ctx, netmapContractKey)
} }

View file

@ -49,17 +49,13 @@ const (
var ( var (
configPrefix = []byte("config") configPrefix = []byte("config")
ctx storage.Context
) )
func init() {
ctx = storage.GetContext()
}
// Init function sets up initial list of inner ring public keys and should // Init function sets up initial list of inner ring public keys and should
// be invoked once at neofs infrastructure setup. // be invoked once at neofs infrastructure setup.
func Init(owner interop.Hash160, keys []interop.PublicKey) { func Init(owner interop.Hash160, keys []interop.PublicKey) {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -87,6 +83,8 @@ func Init(owner interop.Hash160, keys []interop.PublicKey) {
} }
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -99,14 +97,18 @@ func Migrate(script []byte, manifest []byte) bool {
} }
func InnerRingList() []common.IRNode { func InnerRingList() []common.IRNode {
ctx := storage.GetReadOnlyContext()
return getIRNodes(ctx) return getIRNodes(ctx)
} }
func Multiaddress() []byte { func Multiaddress() []byte {
ctx := storage.GetReadOnlyContext()
return multiaddress(getIRNodes(ctx)) return multiaddress(getIRNodes(ctx))
} }
func UpdateInnerRing(keys []interop.PublicKey) bool { func UpdateInnerRing(keys []interop.PublicKey) bool {
ctx := storage.GetContext()
multiaddr := Multiaddress() multiaddr := Multiaddress()
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("updateInnerRing: this method must be invoked by inner ring nodes") panic("updateInnerRing: this method must be invoked by inner ring nodes")
@ -126,6 +128,8 @@ func UpdateInnerRing(keys []interop.PublicKey) bool {
} }
func AddPeer(nodeInfo []byte) bool { func AddPeer(nodeInfo []byte) bool {
ctx := storage.GetContext()
multiaddr := Multiaddress() multiaddr := Multiaddress()
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
publicKey := nodeInfo[2:35] // offset:2, len:33 publicKey := nodeInfo[2:35] // offset:2, len:33
@ -157,6 +161,8 @@ func UpdateState(state int, publicKey interop.PublicKey) bool {
panic("updateState: incorrect public key") panic("updateState: incorrect public key")
} }
ctx := storage.GetContext()
multiaddr := Multiaddress() multiaddr := Multiaddress()
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
if !runtime.CheckWitness(publicKey) { if !runtime.CheckWitness(publicKey) {
@ -181,6 +187,8 @@ func UpdateState(state int, publicKey interop.PublicKey) bool {
} }
func NewEpoch(epochNum int) bool { func NewEpoch(epochNum int) bool {
ctx := storage.GetContext()
multiaddr := Multiaddress() multiaddr := Multiaddress()
if !runtime.CheckWitness(multiaddr) { if !runtime.CheckWitness(multiaddr) {
panic("newEpoch: this method must be invoked by inner ring nodes") panic("newEpoch: this method must be invoked by inner ring nodes")
@ -211,15 +219,18 @@ func NewEpoch(epochNum int) bool {
} }
func Epoch() int { func Epoch() int {
ctx := storage.GetReadOnlyContext()
return storage.Get(ctx, snapshotEpoch).(int) return storage.Get(ctx, snapshotEpoch).(int)
} }
func Netmap() []storageNode { func Netmap() []storageNode {
ctx := storage.GetReadOnlyContext()
return getSnapshot(ctx, snapshot0Key) return getSnapshot(ctx, snapshot0Key)
} }
func Snapshot(diff int) []storageNode { func Snapshot(diff int) []storageNode {
var key string var key string
switch diff { switch diff {
case 0: case 0:
key = snapshot0Key key = snapshot0Key
@ -229,16 +240,19 @@ func Snapshot(diff int) []storageNode {
panic("snapshot: incorrect diff") panic("snapshot: incorrect diff")
} }
ctx := storage.GetReadOnlyContext()
return getSnapshot(ctx, key) return getSnapshot(ctx, key)
} }
func SnapshotByEpoch(epoch int) []storageNode { func SnapshotByEpoch(epoch int) []storageNode {
ctx := storage.GetReadOnlyContext()
currentEpoch := storage.Get(ctx, snapshotEpoch).(int) currentEpoch := storage.Get(ctx, snapshotEpoch).(int)
return Snapshot(currentEpoch - epoch) return Snapshot(currentEpoch - epoch)
} }
func Config(key []byte) interface{} { func Config(key []byte) interface{} {
ctx := storage.GetReadOnlyContext()
return getConfig(ctx, key) return getConfig(ctx, key)
} }
@ -248,6 +262,8 @@ func SetConfig(id, key, val []byte) bool {
panic("setConfig: invoked by non inner ring node") panic("setConfig: invoked by non inner ring node")
} }
ctx := storage.GetContext()
setConfig(ctx, key, val) setConfig(ctx, key, val)
runtime.Log("setConfig: configuration has been updated") runtime.Log("setConfig: configuration has been updated")
@ -256,6 +272,8 @@ func SetConfig(id, key, val []byte) bool {
} }
func InitConfig(args [][]byte) bool { func InitConfig(args [][]byte) bool {
ctx := storage.GetContext()
if storage.Get(ctx, configuredKey) != nil { if storage.Get(ctx, configuredKey) != nil {
panic("netmap: configuration already installed") panic("netmap: configuration already installed")
} }
@ -279,6 +297,8 @@ func InitConfig(args [][]byte) bool {
} }
func ListConfig() []record { func ListConfig() []record {
ctx := storage.GetReadOnlyContext()
var config []record var config []record
it := storage.Find(ctx, configPrefix, storage.None) it := storage.Find(ctx, configPrefix, storage.None)

View file

@ -15,12 +15,6 @@ const (
netmapContractKey = "netmapScriptHash" netmapContractKey = "netmapScriptHash"
) )
var ctx storage.Context
func init() {
ctx = storage.GetContext()
}
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
caller := runtime.GetCallingScriptHash() caller := runtime.GetCallingScriptHash()
if !common.BytesEqual(caller, []byte(gas.Hash)) { if !common.BytesEqual(caller, []byte(gas.Hash)) {
@ -29,6 +23,8 @@ func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
} }
func Init(owner, addrNetmap interop.Hash160) { func Init(owner, addrNetmap interop.Hash160) {
ctx := storage.GetContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
panic("only owner can reinitialize contract") panic("only owner can reinitialize contract")
} }
@ -44,6 +40,8 @@ func Init(owner, addrNetmap interop.Hash160) {
} }
func Migrate(script []byte, manifest []byte) bool { func Migrate(script []byte, manifest []byte) bool {
ctx := storage.GetReadOnlyContext()
if !common.HasUpdateAccess(ctx) { if !common.HasUpdateAccess(ctx) {
runtime.Log("only owner can update contract") runtime.Log("only owner can update contract")
return false return false
@ -56,7 +54,9 @@ func Migrate(script []byte, manifest []byte) bool {
} }
func Verify() bool { func Verify() bool {
ctx := storage.GetReadOnlyContext()
sig := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) sig := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
return runtime.CheckWitness(sig) return runtime.CheckWitness(sig)
} }