github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/states/account_state.go (about)

     1  package states
     2  
     3  import (
     4  	"encoding/binary"
     5  	"math/big"
     6  	"sort"
     7  
     8  	"github.com/sixexorg/magnetic-ring/common/sink"
     9  
    10  	"io"
    11  
    12  	"io/ioutil"
    13  
    14  	"bytes"
    15  
    16  	"encoding/gob"
    17  
    18  	"github.com/sixexorg/magnetic-ring/common"
    19  	"github.com/sixexorg/magnetic-ring/errors"
    20  	mcom "github.com/sixexorg/magnetic-ring/store/mainchain/common"
    21  )
    22  
    23  func init() {
    24  	gob.Register(&big.Int{})
    25  }
    26  
    27  type AccountState struct {
    28  	Address     common.Address
    29  	hash        common.Hash
    30  	Height      uint64
    31  	Data        *Account
    32  	LeftBalance *big.Int //only for accountlevel
    33  }
    34  
    35  type Account struct {
    36  	Nonce       uint64
    37  	Balance     *big.Int
    38  	EnergyBalance *big.Int
    39  	BonusHeight uint64
    40  }
    41  
    42  func (this *AccountState) GetHeight() uint64 {
    43  	return this.Height
    44  }
    45  func (this *AccountState) GetVal() interface{} {
    46  	return this.Data.Balance
    47  }
    48  
    49  type AccountStates []*AccountState
    50  
    51  func (s AccountStates) Len() int           { return len(s) }
    52  func (s AccountStates) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
    53  func (s AccountStates) Less(i, j int) bool { return s[i].Hash().String() < s[j].Hash().String() }
    54  func (s AccountStates) GetHashRoot() common.Hash {
    55  	sort.Sort(s)
    56  	hashes := make([]common.Hash, 0, s.Len())
    57  	for _, v := range s {
    58  		hashes = append(hashes, v.Hash())
    59  	}
    60  	return common.ComputeMerkleRoot(hashes)
    61  }
    62  
    63  func (this *AccountState) Hash() common.Hash {
    64  	buff := new(bytes.Buffer)
    65  	buff.Write(this.GetKey())
    66  	this.Serialize(buff)
    67  	hash, _ := common.ParseHashFromBytes(common.Sha256(buff.Bytes()))
    68  	this.hash = hash
    69  	return hash
    70  }
    71  func (this *AccountState) Serialize(w io.Writer) error {
    72  	sk := sink.NewZeroCopySink(nil)
    73  	sk.WriteUint64(this.Data.Nonce)
    74  	c1, _ := sink.BigIntToComplex(this.Data.Balance)
    75  	sk.WriteComplex(c1)
    76  	c2, _ := sink.BigIntToComplex(this.Data.EnergyBalance)
    77  	sk.WriteComplex(c2)
    78  	sk.WriteUint64(this.Data.BonusHeight)
    79  	w.Write(sk.Bytes())
    80  	return nil
    81  }
    82  
    83  func (this *AccountState) Deserialize(r io.Reader) error {
    84  	buff, err := ioutil.ReadAll(r)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	var eof bool
    89  	source := sink.NewZeroCopySource(buff)
    90  	_, eof = source.NextByte()
    91  	this.Address, eof = source.NextAddress()
    92  	this.Height, eof = source.NextUint64()
    93  	this.Data = &Account{}
    94  	this.Data.Nonce, eof = source.NextUint64()
    95  	bal, eof := source.NextComplex()
    96  	this.Data.Balance, err = bal.ComplexToBigInt()
    97  	if err != nil {
    98  		return err
    99  	}
   100  	bbl, eof := source.NextComplex()
   101  	this.Data.EnergyBalance, err = bbl.ComplexToBigInt()
   102  	if err != nil {
   103  		return err
   104  	}
   105  	this.Data.BonusHeight, eof = source.NextUint64()
   106  	if eof {
   107  		return errors.ERR_TXRAW_EOF
   108  	}
   109  	return nil
   110  }
   111  
   112  func (this *AccountState) GetKey() []byte {
   113  	buff := make([]byte, 1+common.AddrLength+8)
   114  	buff[0] = byte(mcom.ST_ACCOUNT)
   115  	copy(buff[1:common.AddrLength+1], this.Address[:])
   116  	binary.LittleEndian.PutUint64(buff[common.AddrLength+1:], this.Height)
   117  	return buff
   118  }