import (
"context"
- "encoding/binary"
"encoding/json"
- "sort"
"strings"
"sync"
"time"
)
const (
- maxAccountCache = 1000
- aliasPrefix = "ALI:"
- accountPrefix = "ACC:"
- accountCPPrefix = "ACP:"
- indexPrefix = "ACIDX:"
+ maxAccountCache = 1000
+ aliasPrefix = "ALI:"
+ accountCPPrefix = "ACP:"
+ contractIndexPrefix = "ACPI:"
)
-var miningAddressKey = []byte("miningAddress")
+var (
+ miningAddressKey = []byte("miningAddress")
+ accountIndexKey = []byte("accountIndex")
+ accountPrefix = []byte("ACC:")
+)
// pre-define errors for supporting bytom errorFormatter
var (
return []byte(aliasPrefix + name)
}
-func indexKeys(xpubs []chainkd.XPub) []byte {
- xpubStrings := make([]string, len(xpubs))
- for i, xpub := range xpubs {
- xpubStrings[i] = xpub.String()
- }
- sort.Strings(xpubStrings)
- suffix := strings.Join(xpubStrings, "")
-
- return []byte(indexPrefix + suffix)
-}
-
//Key account store prefix
func Key(name string) []byte {
- return []byte(accountPrefix + name)
+ return append(accountPrefix, []byte(name)...)
}
//CPKey account control promgram store prefix
return append([]byte(accountCPPrefix), hash[:]...)
}
-func convertUnit64ToBytes(nextIndex uint64) []byte {
- buf := make([]byte, 8)
- binary.PutUvarint(buf, nextIndex)
- return buf
-}
-
-func convertBytesToUint64(rawIndex []byte) uint64 {
- result, _ := binary.Uvarint(rawIndex)
- return result
+func contractIndexKey(accountID string) []byte {
+ return append([]byte(contractIndexPrefix), []byte(accountID)...)
}
// NewManager creates a new account manager
Alias string
}
-func (m *Manager) getNextXpubsIndex(xpubs []chainkd.XPub) uint64 {
+func (m *Manager) getNextAccountIndex() uint64 {
m.accIndexMu.Lock()
defer m.accIndexMu.Unlock()
var nextIndex uint64 = 1
- if rawIndexBytes := m.db.Get(indexKeys(xpubs)); rawIndexBytes != nil {
- nextIndex = convertBytesToUint64(rawIndexBytes) + 1
+ if rawIndexBytes := m.db.Get(accountIndexKey); rawIndexBytes != nil {
+ nextIndex = common.BytesToUnit64(rawIndexBytes) + 1
}
- m.db.Set(indexKeys(xpubs), convertUnit64ToBytes(nextIndex))
+ m.db.Set(accountIndexKey, common.Unit64ToBytes(nextIndex))
+ return nextIndex
+}
+
+func (m *Manager) getNextContractIndex(accountID string) uint64 {
+ m.accIndexMu.Lock()
+ defer m.accIndexMu.Unlock()
+
+ nextIndex := uint64(1)
+ if rawIndexBytes := m.db.Get(contractIndexKey(accountID)); rawIndexBytes != nil {
+ nextIndex = common.BytesToUnit64(rawIndexBytes) + 1
+ }
+ m.db.Set(contractIndexKey(accountID), common.Unit64ToBytes(nextIndex))
return nextIndex
}
return nil, ErrDuplicateAlias
}
- signer, err := signers.Create("account", xpubs, quorum, m.getNextXpubsIndex(xpubs))
+ signer, err := signers.Create("account", xpubs, quorum, m.getNextAccountIndex())
id := signers.IDGenerate()
if err != nil {
return nil, errors.Wrap(err)
}
func (m *Manager) createP2PKH(ctx context.Context, account *Account, change bool) (*CtrlProgram, error) {
- idx := m.getNextXpubsIndex(account.Signer.XPubs)
+ idx := m.getNextContractIndex(account.ID)
path := signers.Path(account.Signer, signers.AccountKeySpace, idx)
derivedXPubs := chainkd.DeriveXPubs(account.XPubs, path)
derivedPK := derivedXPubs[0].PublicKey()
}
func (m *Manager) createP2SH(ctx context.Context, account *Account, change bool) (*CtrlProgram, error) {
- idx := m.getNextXpubsIndex(account.Signer.XPubs)
+ idx := m.getNextContractIndex(account.ID)
path := signers.Path(account.Signer, signers.AccountKeySpace, idx)
derivedXPubs := chainkd.DeriveXPubs(account.XPubs, path)
derivedPKs := chainkd.XPubKeys(derivedXPubs)
}
// ListAccounts will return the accounts in the db
-func (m *Manager) ListAccounts(id string) ([]*Account, error) {
+func (m *Manager) ListAccounts() ([]*Account, error) {
accounts := []*Account{}
- accountIter := m.db.IteratorPrefix([]byte(accountPrefix + id))
+ accountIter := m.db.IteratorPrefix(accountPrefix)
defer accountIter.Release()
for accountIter.Next() {