forked from TrueCloudLab/frostfs-contract
[#51] container: Support notary contract
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
c6816193d3
commit
f21d09713f
1 changed files with 38 additions and 102 deletions
|
@ -90,21 +90,14 @@ func Migrate(script []byte, manifest []byte) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Put(container, signature, publicKey []byte) bool {
|
func Put(container, signature, publicKey []byte) bool {
|
||||||
netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
|
|
||||||
innerRing := common.InnerRingList(netmapContractAddr)
|
|
||||||
threshold := len(innerRing)/3*2 + 1
|
|
||||||
|
|
||||||
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
|
||||||
containerID := crypto.SHA256(container)
|
containerID := crypto.SHA256(container)
|
||||||
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).([]byte)
|
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).([]byte)
|
||||||
|
|
||||||
// If invoked from storage node, ignore it.
|
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
|
||||||
// Inner ring will find tx, validate it and send it again.
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
irKey := common.InnerRingInvoker(innerRing)
|
|
||||||
if len(irKey) == 0 {
|
|
||||||
// check provided key
|
|
||||||
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).([][]byte)
|
keys := contract.Call(neofsIDContractAddr, "key", contract.ReadOnly, ownerID).([][]byte)
|
||||||
|
@ -119,15 +112,13 @@ func Put(container, signature, publicKey []byte) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
from := walletToScripHash(ownerID)
|
from := walletToScripHash(ownerID)
|
||||||
|
netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
|
||||||
balanceContractAddr := storage.Get(ctx, balanceContractKey).([]byte)
|
balanceContractAddr := storage.Get(ctx, balanceContractKey).([]byte)
|
||||||
containerFee := contract.Call(netmapContractAddr, "config", contract.ReadOnly, containerFeeKey).(int)
|
containerFee := contract.Call(netmapContractAddr, "config", contract.ReadOnly, containerFeeKey).(int)
|
||||||
hashCandidate := common.InvokeID([]interface{}{container, signature, publicKey}, []byte("put"))
|
|
||||||
|
|
||||||
n := common.Vote(ctx, hashCandidate, irKey)
|
|
||||||
if n >= threshold {
|
|
||||||
common.RemoveVotes(ctx, hashCandidate)
|
|
||||||
// todo: check if new container with unique container id
|
// todo: check if new container with unique container id
|
||||||
|
|
||||||
|
innerRing := common.InnerRingList(netmapContractAddr)
|
||||||
for i := 0; i < len(innerRing); i++ {
|
for i := 0; i < len(innerRing); i++ {
|
||||||
node := innerRing[i]
|
node := innerRing[i]
|
||||||
to := contract.CreateStandardAccount(node.PublicKey)
|
to := contract.CreateStandardAccount(node.PublicKey)
|
||||||
|
@ -140,36 +131,26 @@ func Put(container, signature, publicKey []byte) bool {
|
||||||
containerFeeTransferMsg, // consider add container id to the message
|
containerFeeTransferMsg, // consider add container id to the message
|
||||||
)
|
)
|
||||||
if !tx.(bool) {
|
if !tx.(bool) {
|
||||||
// todo: consider using `return false` to remove votes
|
|
||||||
panic("put: can't transfer assets for container creation")
|
panic("put: can't transfer assets for container creation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addContainer(ctx, containerID, ownerID, container)
|
addContainer(ctx, containerID, ownerID, container)
|
||||||
// try to remove underscore at v0.92.0
|
contract.Call(neofsIDContractAddr, "addKey", contract.All, ownerID, [][]byte{publicKey})
|
||||||
_ = contract.Call(neofsIDContractAddr, "addKey", contract.All, ownerID, [][]byte{publicKey})
|
|
||||||
|
|
||||||
runtime.Log("put: added new container")
|
runtime.Log("put: added new container")
|
||||||
} else {
|
|
||||||
runtime.Log("put: processed invoke from inner ring")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func Delete(containerID, signature []byte) bool {
|
func Delete(containerID, signature []byte) bool {
|
||||||
innerRing := irList()
|
|
||||||
threshold := len(innerRing)/3*2 + 1
|
|
||||||
|
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If invoked from storage node, ignore it.
|
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
|
||||||
// Inner ring will find tx, validate it and send it again.
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
irKey := common.InnerRingInvoker(innerRing)
|
|
||||||
if len(irKey) == 0 {
|
|
||||||
// check provided key
|
// check provided key
|
||||||
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).([]byte)
|
neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).([]byte)
|
||||||
keys := contract.Call(neofsIDContractAddr, "key", contract.ReadOnly, ownerID).([][]byte)
|
keys := contract.Call(neofsIDContractAddr, "key", contract.ReadOnly, ownerID).([][]byte)
|
||||||
|
@ -182,16 +163,8 @@ func Delete(containerID, signature []byte) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
hashCandidate := common.InvokeID([]interface{}{containerID, signature}, []byte("delete"))
|
|
||||||
|
|
||||||
n := common.Vote(ctx, hashCandidate, irKey)
|
|
||||||
if n >= threshold {
|
|
||||||
common.RemoveVotes(ctx, hashCandidate)
|
|
||||||
removeContainer(ctx, containerID, ownerID)
|
removeContainer(ctx, containerID, ownerID)
|
||||||
runtime.Log("delete: remove container")
|
runtime.Log("delete: remove container")
|
||||||
} else {
|
|
||||||
runtime.Log("delete: processed invoke from inner ring")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -344,70 +317,37 @@ func ListContainerSizes(epoch int) [][]byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProcessEpoch(epochNum int) {
|
func ProcessEpoch(epochNum int) {
|
||||||
innerRing := irList()
|
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
|
||||||
threshold := len(innerRing)/3*2 + 1
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
|
|
||||||
irKey := common.InnerRingInvoker(innerRing)
|
|
||||||
if len(irKey) == 0 {
|
|
||||||
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(epochNum)
|
||||||
epochID := common.InvokeID([]interface{}{epochNum}, []byte("epoch"))
|
for _, candidate := range candidates {
|
||||||
|
|
||||||
n := common.Vote(ctx, epochID, irKey)
|
|
||||||
if n >= threshold {
|
|
||||||
common.RemoveVotes(ctx, epochID)
|
|
||||||
|
|
||||||
for i := range candidates {
|
|
||||||
candidate := candidates[i]
|
|
||||||
storage.Delete(ctx, candidate)
|
storage.Delete(ctx, candidate)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartContainerEstimation(epoch int) bool {
|
func StartContainerEstimation(epoch int) bool {
|
||||||
innerRing := irList()
|
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
|
||||||
threshold := len(innerRing)/3*2 + 1
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
|
|
||||||
irKey := common.InnerRingInvoker(innerRing)
|
|
||||||
if len(irKey) == 0 {
|
|
||||||
panic("startEstimation: only inner ring nodes can invoke this")
|
panic("startEstimation: only inner ring nodes can invoke this")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashCandidate := common.InvokeID([]interface{}{epoch}, []byte("startEstimation"))
|
|
||||||
|
|
||||||
n := common.Vote(ctx, hashCandidate, irKey)
|
|
||||||
if n >= threshold {
|
|
||||||
common.RemoveVotes(ctx, hashCandidate)
|
|
||||||
runtime.Notify("StartEstimation", epoch)
|
runtime.Notify("StartEstimation", epoch)
|
||||||
runtime.Log("startEstimation: notification has been produced")
|
runtime.Log("startEstimation: notification has been produced")
|
||||||
} else {
|
|
||||||
runtime.Log("startEstimation: processed invoke from inner ring")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func StopContainerEstimation(epoch int) bool {
|
func StopContainerEstimation(epoch int) bool {
|
||||||
innerRing := irList()
|
multiaddr := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey)
|
||||||
threshold := len(innerRing)/3*2 + 1
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
|
|
||||||
irKey := common.InnerRingInvoker(innerRing)
|
|
||||||
if len(irKey) == 0 {
|
|
||||||
panic("stopEstimation: only inner ring nodes can invoke this")
|
panic("stopEstimation: only inner ring nodes can invoke this")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashCandidate := common.InvokeID([]interface{}{epoch}, []byte("stopEstimation"))
|
|
||||||
|
|
||||||
n := common.Vote(ctx, hashCandidate, irKey)
|
|
||||||
if n >= threshold {
|
|
||||||
common.RemoveVotes(ctx, hashCandidate)
|
|
||||||
runtime.Notify("StopEstimation", epoch)
|
runtime.Notify("StopEstimation", epoch)
|
||||||
runtime.Log("stopEstimation: notification has been produced")
|
runtime.Log("stopEstimation: notification has been produced")
|
||||||
} else {
|
|
||||||
runtime.Log("stopEstimation: processed invoke from inner ring")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -600,7 +540,3 @@ func keysToDelete(epoch int) [][]byte {
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
func irList() []common.IRNode {
|
|
||||||
return common.InnerRingListViaStorage(ctx, netmapContractKey)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue