github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/examples/xo_javascript/xo_state.js (about)

     1  /**
     2   * Copyright 2018 Intel Corporation
     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  
    18  'use strict'
    19  
    20  const crypto = require('crypto')
    21  
    22  class XoState {
    23    constructor (context) {
    24      this.context = context
    25      this.addressCache = new Map([])
    26      this.timeout = 500 // Timeout in milliseconds
    27    }
    28  
    29    getGame (name) {
    30      return this._loadGames(name).then((games) => games.get(name))
    31    }
    32  
    33    setGame (name, game) {
    34      let address = _makeXoAddress(name)
    35  
    36      return this._loadGames(name).then((games) => {
    37        games.set(name, game)
    38        return games
    39      }).then((games) => {
    40        let data = _serialize(games)
    41  
    42        this.addressCache.set(address, data)
    43        let entries = {
    44          [address]: data
    45        }
    46        return this.context.setState(entries, this.timeout)
    47      })
    48    }
    49  
    50    deleteGame (name) {
    51      let address = _makeXoAddress(name)
    52      return this._loadGames(name).then((games) => {
    53        games.delete(name)
    54  
    55        if (games.size === 0) {
    56          this.addressCache.set(address, null)
    57          return this.context.deleteState([address], this.timeout)
    58        } else {
    59          let data = _serialize(games)
    60          this.addressCache.set(address, data)
    61          let entries = {
    62            [address]: data
    63          }
    64          return this.context.setState(entries, this.timeout)
    65        }
    66      })
    67    }
    68  
    69    _loadGames (name) {
    70      let address = _makeXoAddress(name)
    71      if (this.addressCache.has(address)) {
    72        if (this.addressCache.get(address) === null) {
    73          return Promise.resolve(new Map([]))
    74        } else {
    75          return Promise.resolve(_deserialize(this.addressCache.get(address)))
    76        }
    77      } else {
    78        return this.context.getState([address], this.timeout)
    79          .then((addressValues) => {
    80            if (!addressValues[address].toString()) {
    81              this.addressCache.set(address, null)
    82              return new Map([])
    83            } else {
    84              let data = addressValues[address].toString()
    85              this.addressCache.set(address, data)
    86              return _deserialize(data)
    87            }
    88          })
    89      }
    90    }
    91  }
    92  
    93  const _hash = (x) =>
    94    crypto.createHash('sha512').update(x).digest('hex').toLowerCase().substring(0, 64)
    95  
    96  const XO_FAMILY = 'xo'
    97  
    98  const XO_NAMESPACE = _hash(XO_FAMILY).substring(0, 6)
    99  
   100  const _makeXoAddress = (x) => XO_NAMESPACE + _hash(x)
   101  
   102  module.exports = {
   103    XO_NAMESPACE,
   104    XO_FAMILY,
   105    XoState
   106  }
   107  
   108  const _deserialize = (data) => {
   109    let gamesIterable = data.split('|').map(x => x.split(','))
   110      .map(x => [x[0], {name: x[0], board: x[1], state: x[2], player1: x[3], player2: x[4]}])
   111    return new Map(gamesIterable)
   112  }
   113  
   114  const _serialize = (games) => {
   115    let gameStrs = []
   116    for (let nameGame of games) {
   117      let name = nameGame[0]
   118      let game = nameGame[1]
   119      gameStrs.push([name, game.board, game.state, game.player1, game.player2].join(','))
   120    }
   121  
   122    gameStrs.sort()
   123  
   124    return Buffer.from(gameStrs.join('|'))
   125  }