github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/core/ledger/kvledger/txmgmt/statedb/statedb.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package statedb
    18  
    19  import (
    20  	"sort"
    21  
    22  	"math/big"
    23  
    24  	"encoding/json"
    25  
    26  	"github.com/inklabsfoundation/inkchain/core/ledger/kvledger/txmgmt/version"
    27  	"github.com/inklabsfoundation/inkchain/core/ledger/util"
    28  )
    29  
    30  // VersionedDBProvider provides an instance of an versioned DB
    31  type VersionedDBProvider interface {
    32  	// GetDBHandle returns a handle to a VersionedDB
    33  	GetDBHandle(id string) (VersionedDB, error)
    34  	// Close closes all the VersionedDB instances and releases any resources held by VersionedDBProvider
    35  	Close()
    36  }
    37  
    38  // VersionedDB lists methods that a db is supposed to implement
    39  type VersionedDB interface {
    40  	// GetState gets the value for given namespace and key. For a chaincode, the namespace corresponds to the chaincodeId
    41  	GetState(namespace string, key string) (*VersionedValue, error)
    42  	// GetStateMultipleKeys gets the values for multiple keys in a single call
    43  	GetStateMultipleKeys(namespace string, keys []string) ([]*VersionedValue, error)
    44  	// GetStateRangeScanIterator returns an iterator that contains all the key-values between given key ranges.
    45  	// startKey is inclusive
    46  	// endKey is exclusive
    47  	// The returned ResultsIterator contains results of type *VersionedKV
    48  	GetStateRangeScanIterator(namespace string, startKey string, endKey string) (ResultsIterator, error)
    49  	// ExecuteQuery executes the given query and returns an iterator that contains results of type *VersionedKV.
    50  	ExecuteQuery(namespace, query string) (ResultsIterator, error)
    51  	// ApplyUpdates applies the batch to the underlying db.
    52  	// height is the height of the highest transaction in the Batch that
    53  	// a state db implementation is expected to ues as a save point
    54  	ApplyUpdates(batch *UpdateBatch, height *version.Height) error
    55  	// GetLatestSavePoint returns the height of the highest transaction upto which
    56  	// the state db is consistent
    57  	GetLatestSavePoint() (*version.Height, error)
    58  	// ValidateKey tests whether the key is supported by the db implementation.
    59  	// For instance, leveldb supports any bytes for the key while the couchdb supports only valid utf-8 string
    60  	ValidateKey(key string) error
    61  	// Open opens the db
    62  	Open() error
    63  	// Close closes the db
    64  	Close()
    65  }
    66  
    67  // CompositeKey encloses Namespace and Key components
    68  type CompositeKey struct {
    69  	Namespace string
    70  	Key       string
    71  }
    72  
    73  // VersionedValue encloses value and corresponding version
    74  type VersionedValue struct {
    75  	Value   []byte
    76  	Version *version.Height
    77  }
    78  
    79  // VersionedKV encloses key and corresponding VersionedValue
    80  type VersionedKV struct {
    81  	CompositeKey
    82  	VersionedValue
    83  }
    84  
    85  // ResultsIterator hepls in iterates over query results
    86  type ResultsIterator interface {
    87  	Next() (QueryResult, error)
    88  	Close()
    89  }
    90  
    91  // QueryResult - a general interface for supporting different types of query results. Actual types differ for different queries
    92  type QueryResult interface{}
    93  
    94  type nsUpdates struct {
    95  	m map[string]*VersionedValue
    96  }
    97  
    98  func newNsUpdates() *nsUpdates {
    99  	return &nsUpdates{make(map[string]*VersionedValue)}
   100  }
   101  
   102  // UpdateBatch encloses the details of multiple `updates`
   103  type UpdateBatch struct {
   104  	updates map[string]*nsUpdates
   105  }
   106  
   107  // NewUpdateBatch constructs an instance of a Batch
   108  func NewUpdateBatch() *UpdateBatch {
   109  	return &UpdateBatch{make(map[string]*nsUpdates)}
   110  }
   111  
   112  // Get returns the VersionedValue for the given namespace and key
   113  func (batch *UpdateBatch) Get(ns string, key string) *VersionedValue {
   114  	nsUpdates, ok := batch.updates[ns]
   115  	if !ok {
   116  		return nil
   117  	}
   118  	vv, ok := nsUpdates.m[key]
   119  	if !ok {
   120  		return nil
   121  	}
   122  	return vv
   123  }
   124  
   125  // Put adds a VersionedKV
   126  func (batch *UpdateBatch) Put(ns string, key string, value []byte, version *version.Height) {
   127  	if value == nil {
   128  		panic("Nil value not allowed")
   129  	}
   130  	nsUpdates := batch.getOrCreateNsUpdates(ns)
   131  	nsUpdates.m[key] = &VersionedValue{value, version}
   132  }
   133  
   134  // Delete deletes a Key and associated value
   135  func (batch *UpdateBatch) Delete(ns string, key string, version *version.Height) {
   136  	nsUpdates := batch.getOrCreateNsUpdates(ns)
   137  	nsUpdates.m[key] = &VersionedValue{nil, version}
   138  }
   139  
   140  // Exists checks whether the given key exists in the batch
   141  func (batch *UpdateBatch) Exists(ns string, key string) bool {
   142  	nsUpdates, ok := batch.updates[ns]
   143  	if !ok {
   144  		return false
   145  	}
   146  	_, ok = nsUpdates.m[key]
   147  	return ok
   148  }
   149  
   150  // GetUpdatedNamespaces returns the names of the namespaces that are updated
   151  func (batch *UpdateBatch) GetUpdatedNamespaces() []string {
   152  	namespaces := make([]string, len(batch.updates))
   153  	i := 0
   154  	for ns := range batch.updates {
   155  		namespaces[i] = ns
   156  		i++
   157  	}
   158  	return namespaces
   159  }
   160  
   161  // GetUpdates returns all the updates for a namespace
   162  func (batch *UpdateBatch) GetUpdates(ns string) map[string]*VersionedValue {
   163  	nsUpdates, ok := batch.updates[ns]
   164  	if !ok {
   165  		return nil
   166  	}
   167  	return nsUpdates.m
   168  }
   169  
   170  // GetRangeScanIterator returns an iterator that iterates over keys of a specific namespace in sorted order
   171  // In other word this gives the same functionality over the contents in the `UpdateBatch` as
   172  // `VersionedDB.GetStateRangeScanIterator()` method gives over the contents in the statedb
   173  // This function can be used for querying the contents in the updateBatch before they are committed to the statedb.
   174  // For instance, a validator implementation can used this to verify the validity of a range query of a transaction
   175  // where the UpdateBatch represents the union of the modifications performed by the preceding valid transactions in the same block
   176  // (Assuming Group commit approach where we commit all the updates caused by a block together).
   177  func (batch *UpdateBatch) GetRangeScanIterator(ns string, startKey string, endKey string) ResultsIterator {
   178  	return newNsIterator(ns, startKey, endKey, batch)
   179  }
   180  
   181  func (batch *UpdateBatch) getOrCreateNsUpdates(ns string) *nsUpdates {
   182  	nsUpdates := batch.updates[ns]
   183  	if nsUpdates == nil {
   184  		nsUpdates = newNsUpdates()
   185  		batch.updates[ns] = nsUpdates
   186  	}
   187  	return nsUpdates
   188  }
   189  
   190  type nsIterator struct {
   191  	ns         string
   192  	nsUpdates  *nsUpdates
   193  	sortedKeys []string
   194  	nextIndex  int
   195  	lastIndex  int
   196  }
   197  
   198  func newNsIterator(ns string, startKey string, endKey string, batch *UpdateBatch) *nsIterator {
   199  	nsUpdates, ok := batch.updates[ns]
   200  	if !ok {
   201  		return &nsIterator{}
   202  	}
   203  	sortedKeys := util.GetSortedKeys(nsUpdates.m)
   204  	var nextIndex int
   205  	var lastIndex int
   206  	if startKey == "" {
   207  		nextIndex = 0
   208  	} else {
   209  		nextIndex = sort.SearchStrings(sortedKeys, startKey)
   210  	}
   211  	if endKey == "" {
   212  		lastIndex = len(sortedKeys)
   213  	} else {
   214  		lastIndex = sort.SearchStrings(sortedKeys, endKey)
   215  	}
   216  	return &nsIterator{ns, nsUpdates, sortedKeys, nextIndex, lastIndex}
   217  }
   218  
   219  // Next gives next key and versioned value. It returns a nil when exhausted
   220  func (itr *nsIterator) Next() (QueryResult, error) {
   221  	if itr.nextIndex >= itr.lastIndex {
   222  		return nil, nil
   223  	}
   224  	key := itr.sortedKeys[itr.nextIndex]
   225  	vv := itr.nsUpdates.m[key]
   226  	itr.nextIndex++
   227  	return &VersionedKV{CompositeKey{itr.ns, key}, VersionedValue{vv.Value, vv.Version}}, nil
   228  }
   229  
   230  // Close implements the method from QueryResult interface
   231  func (itr *nsIterator) Close() {
   232  	// do nothing
   233  }
   234  
   235  //******************
   236  type TransferAmount struct {
   237  	balanceType string   `json:"balanceType"`
   238  	amount      *big.Int `json:"amount"`
   239  }
   240  
   241  type transferUpdates struct {
   242  	balanceUpdate map[string]*big.Int
   243  	version       *version.Height
   244  	counter       uint64
   245  	ink           *big.Int
   246  	m             map[string]*VersionedValue
   247  }
   248  type TransferBatch struct {
   249  	Updates map[string]*transferUpdates
   250  }
   251  
   252  func newTransferUpdates() *transferUpdates {
   253  	return &transferUpdates{make(map[string]*big.Int), nil, 0, nil, make(map[string]*VersionedValue)}
   254  }
   255  
   256  func NewTransferBatch() *TransferBatch {
   257  	return &TransferBatch{make(map[string]*transferUpdates)}
   258  }
   259  
   260  func (batch *TransferBatch) Put(from string, to string, balanceType string, amount []byte, version *version.Height) {
   261  	if amount == nil {
   262  		return
   263  	}
   264  	fromUpdates := batch.getOrCreateTransferUpdates(from)
   265  	fromBalance, ok := fromUpdates.balanceUpdate[balanceType]
   266  	if !ok {
   267  		fromBalance = big.NewInt(0)
   268  		fromUpdates.balanceUpdate[balanceType] = fromBalance
   269  	}
   270  	amountInt := new(big.Int).SetBytes(amount)
   271  	fromBalance = fromBalance.Sub(fromBalance, amountInt)
   272  	transAmount := &TransferAmount{balanceType: balanceType, amount: amountInt}
   273  	transAmountBytes, _ := json.Marshal(transAmount)
   274  	fromUpdates.m[to] = &VersionedValue{transAmountBytes, version}
   275  	toUpdates := batch.getOrCreateTransferUpdates(to)
   276  	toBalance, ok := toUpdates.balanceUpdate[balanceType]
   277  	if !ok {
   278  		toBalance = big.NewInt(0)
   279  		toUpdates.balanceUpdate[balanceType] = toBalance
   280  	}
   281  
   282  	toBalance = toBalance.Add(toBalance, new(big.Int).SetBytes(amount))
   283  	if fromUpdates.version == nil || (fromUpdates.version != nil && fromUpdates.version.Compare(version) < 0) {
   284  		fromUpdates.version = version
   285  	}
   286  	if toUpdates.version == nil || (toUpdates.version != nil && toUpdates.version.Compare(version) < 0) {
   287  		toUpdates.version = version
   288  	}
   289  }
   290  
   291  func (batch *TransferBatch) getOrCreateTransferUpdates(from string) *transferUpdates {
   292  	transferUpdates, ok := batch.Updates[from]
   293  	if !ok {
   294  		transferUpdates = newTransferUpdates()
   295  		batch.Updates[from] = transferUpdates
   296  	}
   297  	return transferUpdates
   298  }
   299  
   300  func (batch *TransferBatch) UpdateSender(from string, counter uint64, ink *big.Int, version *version.Height) {
   301  	transferUpdates, ok := batch.Updates[from]
   302  	if !ok {
   303  		transferUpdates = newTransferUpdates()
   304  		batch.Updates[from] = transferUpdates
   305  	}
   306  	transferUpdates.version = version
   307  	transferUpdates.counter = counter + 1
   308  	if transferUpdates.ink == nil {
   309  		transferUpdates.ink = ink
   310  	} else {
   311  		transferUpdates.ink = ink.Add(transferUpdates.ink, ink)
   312  	}
   313  }
   314  func (batch *TransferBatch) GetSenderCounter(from string) (uint64, bool) {
   315  	transferUpdates, ok := batch.Updates[from]
   316  	if !ok {
   317  		return 0, ok
   318  	}
   319  	return transferUpdates.counter, ok
   320  }
   321  
   322  func (batch *TransferBatch) GetSenderInk(from string) (*big.Int, bool) {
   323  	transferUpdates, ok := batch.Updates[from]
   324  	if !ok {
   325  		return nil, ok
   326  	}
   327  	return transferUpdates.ink, ok
   328  }
   329  func (batch *TransferBatch) ExistsFrom(from string) bool {
   330  	_, ok := batch.Updates[from]
   331  	return ok
   332  }
   333  func (batch *TransferBatch) ExistsTransfer(from string, to string) bool {
   334  	transferUpdates, ok := batch.Updates[from]
   335  	if !ok {
   336  		return false
   337  	}
   338  	_, ok = transferUpdates.m[to]
   339  	return ok
   340  }
   341  func (batch *TransferBatch) GetBalanceUpdate(from string, balanceType string) *big.Int {
   342  	transferUpdates, ok := batch.Updates[from]
   343  	if !ok {
   344  		return nil
   345  	}
   346  	balance, ok := transferUpdates.balanceUpdate[balanceType]
   347  	if !ok {
   348  		return nil
   349  	}
   350  	return balance
   351  }
   352  func (batch *TransferBatch) GetAllBalanceUpdates(from string) map[string]*big.Int {
   353  	transferUpdates, ok := batch.Updates[from]
   354  	if !ok {
   355  		return nil
   356  	}
   357  	return transferUpdates.balanceUpdate
   358  }
   359  func (batch *TransferBatch) GetBalanceVersion(from string) *version.Height {
   360  	transferUpdates, ok := batch.Updates[from]
   361  	if !ok {
   362  		return nil
   363  	}
   364  	return transferUpdates.version
   365  }
   366  func (batch *TransferBatch) Get(from string, to string) *VersionedValue {
   367  	transferUpdates, ok := batch.Updates[from]
   368  	if !ok {
   369  		return nil
   370  	}
   371  	vv, ok := transferUpdates.m[to]
   372  	if !ok {
   373  		return nil
   374  	}
   375  	return vv
   376  }