OSDN Git Service

Save create asset and create account key index (#304)
authoryahtoo <yahtoo.ma@gmail.com>
Thu, 18 Jan 2018 09:37:53 +0000 (17:37 +0800)
committerPaladz <yzhu101@uottawa.ca>
Thu, 18 Jan 2018 09:37:53 +0000 (17:37 +0800)
* Save create asset and create account key index

* Add key index read/write lock

blockchain/account/accounts.go
blockchain/asset/asset.go
blockchain/signers/idgenerate.go
blockchain/signers/signers.go

index 3f176a8..37e63f8 100755 (executable)
@@ -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)
        }
index acc96f3..121d0ae 100755 (executable)
@@ -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
        }
index 6f05cf7..47afe36 100755 (executable)
@@ -9,22 +9,22 @@ import (
 )
 
 //1<seq_id ,increase by 1
-var seqID uint32 = 0
+var seqID uint32
 
-func nextSeqId() uint32 {
+func nextSeqID() uint32 {
 
        atomic.AddUint32(&seqID, 1)
 
        return seqID
 }
 
-// see the SQL function next_cahin_id in schema.sql on https://github.com/chain/chain
-func IdGenerate() (string, uint64) {
+//IDGenerate generate signer unique id
+func IDGenerate() string {
        var ourEpochMS uint64 = 1496635208000
        var n uint64
 
        nowMS := uint64(time.Now().UnixNano() / 1e6)
-       seqIndex := uint64(nextSeqId())
+       seqIndex := uint64(nextSeqID())
        seqID := uint64(seqIndex % 1024)
        shardID := uint64(5)
 
@@ -36,6 +36,6 @@ func IdGenerate() (string, uint64) {
        binary.BigEndian.PutUint64(bin, n)
        encodeString := base32.HexEncoding.WithPadding(base32.NoPadding).EncodeToString(bin)
 
-       return encodeString, seqIndex
+       return encodeString
 
 }
index 7fe5cf6..bf98f81 100755 (executable)
@@ -67,7 +67,7 @@ func Path(s *Signer, ks keySpace, itemIndexes ...uint64) [][]byte {
 }
 
 // Create creates and stores a Signer in the database
-func Create(signerType string, xpubs []chainkd.XPub, quorum int) (string, *Signer, error) {
+func Create(signerType string, xpubs []chainkd.XPub, quorum int, keyIndex uint64) (string, *Signer, error) {
        if len(xpubs) == 0 {
                return "", nil, errors.Wrap(ErrNoXPubs)
        }
@@ -83,7 +83,7 @@ func Create(signerType string, xpubs []chainkd.XPub, quorum int) (string, *Signe
                return "", nil, errors.Wrap(ErrBadQuorum)
        }
 
-       id, keyIndex := IdGenerate()
+       id := IDGenerate()
        return id, &Signer{
                Type:     signerType,
                XPubs:    xpubs,