-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathaccountlock.go
88 lines (71 loc) · 1.88 KB
/
accountlock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package baseapp
import (
"encoding/binary"
"sort"
"sync"
sdk "github.com/line/lbm-sdk/v2/types"
)
// NOTE should 1 <= sampleBytes <= 4. If modify it, you should revise `getAddressKey()` as well
const sampleBytes = 2
type AccountLock struct {
accMtx [1 << (sampleBytes * 8)]sync.Mutex
}
func (al *AccountLock) Lock(ctx sdk.Context, tx sdk.Tx) []uint32 {
if !ctx.IsCheckTx() || ctx.IsReCheckTx() {
return nil
}
signers := getSigners(tx)
accKeys := getUniqSortedAddressKey(signers)
for _, key := range accKeys {
al.accMtx[key].Lock()
}
return accKeys
}
func (al *AccountLock) Unlock(accKeys []uint32) {
// NOTE reverse order
for i, length := 0, len(accKeys); i < length; i++ {
key := accKeys[length-1-i]
al.accMtx[key].Unlock()
}
}
func getSigners(tx sdk.Tx) []sdk.AccAddress {
seen := map[string]bool{}
var signers []sdk.AccAddress
for _, msg := range tx.GetMsgs() {
for _, addr := range msg.GetSigners() {
if !seen[addr.String()] {
signers = append(signers, addr)
seen[addr.String()] = true
}
}
}
return signers
}
func getUniqSortedAddressKey(addrs []sdk.AccAddress) []uint32 {
accKeys := make([]uint32, 0, len(addrs))
for _, addr := range addrs {
accKeys = append(accKeys, getAddressKey(addr))
}
accKeys = uniq(accKeys)
sort.Sort(uint32Slice(accKeys))
return accKeys
}
func getAddressKey(addr sdk.AccAddress) uint32 {
return uint32(binary.BigEndian.Uint16(addr))
}
func uniq(u []uint32) []uint32 {
seen := map[uint32]bool{}
var ret []uint32
for _, v := range u {
if !seen[v] {
ret = append(ret, v)
seen[v] = true
}
}
return ret
}
// Uint32Slice attaches the methods of Interface to []uint32, sorting in increasing order.
type uint32Slice []uint32
func (p uint32Slice) Len() int { return len(p) }
func (p uint32Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }