forked from TrueCloudLab/frostfs-contract
[#74] container: Support notary disabled work flow
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
6e8bef671a
commit
400b9bebb4
1 changed files with 134 additions and 14 deletions
|
@ -96,6 +96,7 @@ 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()
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
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
|
||||||
|
@ -103,8 +104,21 @@ func Put(container []byte, signature interop.Signature, publicKey interop.Public
|
||||||
containerID := crypto.Sha256(container)
|
containerID := crypto.Sha256(container)
|
||||||
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).(interop.Hash160)
|
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).(interop.Hash160)
|
||||||
|
|
||||||
|
var ( // for invocation collection without notary
|
||||||
|
alphabet = common.AlphabetNodes()
|
||||||
|
nodeKey []byte
|
||||||
|
alphabetCall bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
nodeKey = common.InnerRingInvoker(alphabet)
|
||||||
|
alphabetCall = len(nodeKey) != 0
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
alphabetCall = runtime.CheckWitness(multiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !alphabetCall {
|
||||||
if !isSignedByOwnerKey(container, signature, ownerID, publicKey) {
|
if !isSignedByOwnerKey(container, signature, ownerID, publicKey) {
|
||||||
// check keys from NeoFSID
|
// check keys from NeoFSID
|
||||||
keys := contract.Call(neofsIDContractAddr, "key", contract.ReadOnly, ownerID).([]interop.PublicKey)
|
keys := contract.Call(neofsIDContractAddr, "key", contract.ReadOnly, ownerID).([]interop.PublicKey)
|
||||||
|
@ -126,7 +140,18 @@ func Put(container []byte, signature interop.Signature, publicKey interop.Public
|
||||||
|
|
||||||
// todo: check if new container with unique container id
|
// todo: check if new container with unique container id
|
||||||
|
|
||||||
alphabet := common.AlphabetNodes()
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
id := common.InvokeID([]interface{}{container, signature, publicKey}, []byte("put"))
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < len(alphabet); i++ {
|
for i := 0; i < len(alphabet); i++ {
|
||||||
node := alphabet[i]
|
node := alphabet[i]
|
||||||
to := contract.CreateStandardAccount(node.PublicKey)
|
to := contract.CreateStandardAccount(node.PublicKey)
|
||||||
|
@ -153,14 +178,29 @@ 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()
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ( // for invocation collection without notary
|
||||||
|
alphabet []common.IRNode
|
||||||
|
nodeKey []byte
|
||||||
|
alphabetCall bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
alphabet = common.AlphabetNodes()
|
||||||
|
nodeKey = common.InnerRingInvoker(alphabet)
|
||||||
|
alphabetCall = len(nodeKey) != 0
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
alphabetCall = runtime.CheckWitness(multiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !alphabetCall {
|
||||||
// check provided key
|
// check provided key
|
||||||
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).(interop.Hash160)
|
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).(interop.Hash160)
|
||||||
keys := contract.Call(neofsIDContractAddr, "key", contract.ReadOnly, ownerID).([]interop.PublicKey)
|
keys := contract.Call(neofsIDContractAddr, "key", contract.ReadOnly, ownerID).([]interop.PublicKey)
|
||||||
|
@ -173,6 +213,18 @@ func Delete(containerID, signature []byte) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
id := common.InvokeID([]interface{}{containerID, signature}, []byte("delete"))
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
removeContainer(ctx, containerID, ownerID)
|
removeContainer(ctx, containerID, ownerID)
|
||||||
runtime.Log("delete: remove container")
|
runtime.Log("delete: remove container")
|
||||||
|
|
||||||
|
@ -341,11 +393,23 @@ func ListContainerSizes(epoch int) [][]byte {
|
||||||
|
|
||||||
func NewEpoch(epochNum int) {
|
func NewEpoch(epochNum int) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
indirectCall := common.FromKnownContract(
|
||||||
|
ctx,
|
||||||
|
runtime.GetCallingScriptHash(),
|
||||||
|
netmapContractKey,
|
||||||
|
)
|
||||||
|
if !indirectCall {
|
||||||
|
panic("newEpoch: this method must be invoked from inner ring")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
panic("newEpoch: this method must be invoked from inner ring")
|
panic("newEpoch: this method must be invoked from inner ring")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
candidates := keysToDelete(ctx, epochNum)
|
candidates := keysToDelete(ctx, epochNum)
|
||||||
for _, candidate := range candidates {
|
for _, candidate := range candidates {
|
||||||
|
@ -354,10 +418,38 @@ func NewEpoch(epochNum int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartContainerEstimation(epoch int) bool {
|
func StartContainerEstimation(epoch int) bool {
|
||||||
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
var ( // for invocation collection without notary
|
||||||
|
alphabet []common.IRNode
|
||||||
|
nodeKey []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
alphabet = common.AlphabetNodes()
|
||||||
|
nodeKey = common.InnerRingInvoker(alphabet)
|
||||||
|
if len(nodeKey) == 0 {
|
||||||
|
panic("startEstimation: only inner ring nodes can invoke this")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
id := common.InvokeID([]interface{}{epoch}, []byte("startEstimation"))
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
runtime.Notify("StartEstimation", epoch)
|
runtime.Notify("StartEstimation", epoch)
|
||||||
runtime.Log("startEstimation: notification has been produced")
|
runtime.Log("startEstimation: notification has been produced")
|
||||||
|
@ -366,10 +458,38 @@ func StartContainerEstimation(epoch int) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func StopContainerEstimation(epoch int) bool {
|
func StopContainerEstimation(epoch int) bool {
|
||||||
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
var ( // for invocation collection without notary
|
||||||
|
alphabet []common.IRNode
|
||||||
|
nodeKey []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
alphabet = common.AlphabetNodes()
|
||||||
|
nodeKey = common.InnerRingInvoker(alphabet)
|
||||||
|
if len(nodeKey) == 0 {
|
||||||
|
panic("stopEstimation: only inner ring nodes can invoke this")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
id := common.InvokeID([]interface{}{epoch}, []byte("stopEstimation"))
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
runtime.Notify("StopEstimation", epoch)
|
runtime.Notify("StopEstimation", epoch)
|
||||||
runtime.Log("stopEstimation: notification has been produced")
|
runtime.Log("stopEstimation: notification has been produced")
|
||||||
|
|
Loading…
Reference in a new issue