From a7680b55295b160e47660c95993b792de26fdfb0 Mon Sep 17 00:00:00 2001 From: yahtoo Date: Thu, 18 Jan 2018 17:37:53 +0800 Subject: [PATCH] Save create asset and create account key index (#304) * Save create asset and create account key index * Add key index read/write lock --- blockchain/account/accounts.go | 29 ++++++++++++++++++++++++++++- blockchain/asset/asset.go | 32 +++++++++++++++++++++++++++++++- blockchain/signers/idgenerate.go | 12 ++++++------ blockchain/signers/signers.go | 4 ++-- 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/blockchain/account/accounts.go b/blockchain/account/accounts.go index 3f176a86..37e63f8e 100755 --- a/blockchain/account/accounts.go +++ b/blockchain/account/accounts.go @@ -30,6 +30,7 @@ const ( accountPrefix = "ACC:" accountCPPrefix = "ACP:" keyNextIndex = "NextIndex" + indexPrefix = "ACIDX:" ) // pre-define errors for supporting bytom errorFormatter @@ -45,6 +46,10 @@ func aliasKey(name string) []byte { return []byte(aliasPrefix + name) } +func indexKey(xpub chainkd.XPub) []byte { + return []byte(indexPrefix + xpub.String()) +} + //Key account store prefix func Key(name string) []byte { return []byte(accountPrefix + name) @@ -88,6 +93,7 @@ type Manager struct { acpMu sync.Mutex acpIndexNext uint64 // next acp index in our block acpIndexCap uint64 // points to end of block + accIndexMu sync.Mutex } // ExpireReservations removes reservations that have expired periodically. @@ -116,13 +122,34 @@ type Account struct { Tags map[string]interface{} `json:"tags"` } +func (m *Manager) getNextAccountIndex(xpubs []chainkd.XPub) (*uint64, error) { + m.accIndexMu.Lock() + defer m.accIndexMu.Unlock() + var nextIndex uint64 = 1 + + if rawIndex := m.db.Get(indexKey(xpubs[0])); rawIndex != nil { + nextIndex = binary.LittleEndian.Uint64(rawIndex) + 1 + } + + buf := make([]byte, 8) + binary.LittleEndian.PutUint64(buf, nextIndex) + m.db.Set(indexKey(xpubs[0]), buf) + + return &nextIndex, nil +} + // Create creates a new Account. func (m *Manager) Create(ctx context.Context, xpubs []chainkd.XPub, quorum int, alias string, tags map[string]interface{}) (*Account, error) { if existed := m.db.Get(aliasKey(alias)); existed != nil { return nil, ErrDuplicateAlias } - id, signer, err := signers.Create("account", xpubs, quorum) + nextAccountIndex, err := m.getNextAccountIndex(xpubs) + if err != nil { + return nil, errors.Wrap(err, "get account index error") + } + + id, signer, err := signers.Create("account", xpubs, quorum, *nextAccountIndex) if err != nil { return nil, errors.Wrap(err) } diff --git a/blockchain/asset/asset.go b/blockchain/asset/asset.go index acc96f36..121d0aea 100755 --- a/blockchain/asset/asset.go +++ b/blockchain/asset/asset.go @@ -2,6 +2,7 @@ package asset import ( "context" + "encoding/binary" "encoding/json" "sync" @@ -25,6 +26,7 @@ const ( maxAssetCache = 1000 assetPrefix = "ASS:" aliasPrefix = "ALS:" + indexPrefix = "ASSIDX:" ) func aliasKey(name string) []byte { @@ -37,6 +39,10 @@ func Key(id *bc.AssetID) []byte { return []byte(assetPrefix + name) } +func indexKey(xpub chainkd.XPub) []byte { + return []byte(indexPrefix + xpub.String()) +} + // pre-define errors for supporting bytom errorFormatter var ( ErrDuplicateAlias = errors.New("duplicate asset alias") @@ -70,6 +76,8 @@ type Registry struct { cacheMu sync.Mutex cache *lru.Cache aliasCache *lru.Cache + + assetIndexMu sync.Mutex } //Asset describe asset on bytom chain @@ -90,6 +98,23 @@ func (asset *Asset) RawDefinition() []byte { return asset.RawDefinitionByte } +func (reg *Registry) getNextAssetIndex(xpubs []chainkd.XPub) (*uint64, error) { + reg.assetIndexMu.Lock() + defer reg.assetIndexMu.Unlock() + + var nextIndex uint64 = 1 + + if rawIndex := reg.db.Get(indexKey(xpubs[0])); rawIndex != nil { + nextIndex = binary.LittleEndian.Uint64(rawIndex) + 1 + } + + buf := make([]byte, 8) + binary.LittleEndian.PutUint64(buf, nextIndex) + reg.db.Set(indexKey(xpubs[0]), buf) + + return &nextIndex, nil +} + // Define defines a new Asset. func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[string]interface{}, alias string, tags map[string]interface{}) (*Asset, error) { if alias == "btm" { @@ -100,7 +125,12 @@ func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[str return nil, ErrDuplicateAlias } - _, assetSigner, err := signers.Create("asset", xpubs, quorum) + nextAssetIndex, err := reg.getNextAssetIndex(xpubs) + if err != nil { + return nil, errors.Wrap(err, "get asset index error") + } + + _, assetSigner, err := signers.Create("asset", xpubs, quorum, *nextAssetIndex) if err != nil { return nil, err } diff --git a/blockchain/signers/idgenerate.go b/blockchain/signers/idgenerate.go index 6f05cf73..47afe366 100755 --- a/blockchain/signers/idgenerate.go +++ b/blockchain/signers/idgenerate.go @@ -9,22 +9,22 @@ import ( ) //1