Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
1d2d3ef
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
zeqing-guo Dec 28, 2018
488cb88
Remove chainMap in dbms and add some test case
zeqing-guo Dec 29, 2018
3d33f3b
Merge branch 'feature/chainBus-SQLChain' of github.com:CovenantSQL/Co…
zeqing-guo Dec 29, 2018
60ae7f7
Merge branch 'feature/chainBus-SQLChain' of github.com:CovenantSQL/Co…
zeqing-guo Dec 29, 2018
f0887e7
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
zeqing-guo Dec 29, 2018
1817668
Fig bug billing incorrect
zeqing-guo Dec 29, 2018
eb2270d
Add debug logs for immutable updating
leventeliu Dec 29, 2018
0a459ea
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
leventeliu Dec 29, 2018
92560fb
Fix typo in log
leventeliu Dec 29, 2018
3a1e1a1
Fix checkPermission error wrap
Dec 29, 2018
6e71909
Fix deadlock
leventeliu Dec 29, 2018
cb63ab4
Fix for GoLint
leventeliu Dec 29, 2018
b025a72
Merge branch 'develop' into feature/chainBus-SQLChain
leventeliu Dec 29, 2018
937b9eb
Update observer period and checkPermission error
Dec 29, 2018
e738045
Fix remote error assertions
leventeliu Dec 29, 2018
a36c6b9
Fix observation test with inconsecutive height
Dec 29, 2018
356e69f
Unify check permission errors
Dec 29, 2018
099bc9d
Merge branch 'develop' into feature/chainBus-SQLChain
xq262144 Dec 29, 2018
171533a
Add lock in UpdatePermission
zeqing-guo Jan 2, 2019
cea134d
Merge branch 'feature/chainBus-SQLChain' of github.com:CovenantSQL/Co…
zeqing-guo Jan 2, 2019
7b665f2
Add GetTokenBalance interface in driver
zeqing-guo Jan 2, 2019
6181c19
Merge branch 'develop' into feature/chainBus-SQLChain
xq262144 Jan 2, 2019
2d89b6e
Merge branch 'develop' into feature/chainBus-SQLChain
xq262144 Jan 2, 2019
9d63edd
Add UpdatePermission and Transfer transaction in cql-util
zeqing-guo Jan 2, 2019
42166a5
Improve cql input format
zeqing-guo Jan 3, 2019
dd84ae8
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
zeqing-guo Jan 3, 2019
fda2ef7
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
zeqing-guo Jan 3, 2019
da76f12
Fix bug: transfer token to sqlchain but not decrease account's token
zeqing-guo Jan 3, 2019
d297f23
Fix some test case
zeqing-guo Jan 3, 2019
09a4684
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
zeqing-guo Jan 3, 2019
223d5a4
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
zeqing-guo Jan 3, 2019
d5466f7
Fix some typos
zeqing-guo Jan 3, 2019
fb566c1
Add revoking permission
zeqing-guo Jan 4, 2019
0cf3f65
Merge remote-tracking branch 'origin/develop' into feature/chainBus-S…
zeqing-guo Jan 4, 2019
d94f188
Merge branch 'bugfix/matchInconsistent' into feature/chainBus-SQLChain
zeqing-guo Jan 4, 2019
7685f7a
Merge branch 'develop' into feature/chainBus-SQLChain
auxten Jan 4, 2019
fccc2a3
Delete JSON Marshal/Unmarshal method
zeqing-guo Jan 4, 2019
46aef03
Merge branch 'develop' into feature/chainBus-SQLChain
xq262144 Jan 4, 2019
b00ecbe
Merge branch 'feature/chainBus-SQLChain' of github.com:CovenantSQL/Co…
zeqing-guo Jan 4, 2019
04a9d52
Move CheckInterval to ChainBusPeriod
zeqing-guo Jan 4, 2019
7900fbb
Change cql output message
zeqing-guo Jan 4, 2019
69090fd
Merge branch 'develop' into feature/chainBus-SQLChain
auxten Jan 4, 2019
9c0a4c7
Remove stable coin and covenant coin interface
zeqing-guo Jan 4, 2019
a9b5c48
Merge branch 'feature/chainBus-SQLChain' of github.com:CovenantSQL/Co…
zeqing-guo Jan 4, 2019
9594849
Rephrase log
xq262144 Jan 4, 2019
8d2fb4b
Rephrase balance update logs
xq262144 Jan 4, 2019
f10b3c9
Ensure there is at least one admin in sqlchain
zeqing-guo Jan 4, 2019
eedd3e9
Merge branch 'feature/chainBus-SQLChain' of github.com:CovenantSQL/Co…
zeqing-guo Jan 4, 2019
b71e2c7
Add withError
zeqing-guo Jan 4, 2019
92f05e2
Change += 1 to ++
zeqing-guo Jan 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions blockproducer/chain_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,10 @@ func (c *Chain) nextNonce(addr proto.AccountAddress) (n pi.AccountNonce, err err
return
}

func (c *Chain) loadAccountCovenantBalance(addr proto.AccountAddress) (balance uint64, ok bool) {
func (c *Chain) loadAccountTokenBalance(addr proto.AccountAddress, tt types.TokenType) (balance uint64, ok bool) {
c.RLock()
defer c.RUnlock()
return c.immutable.loadAccountCovenantBalance(addr)
}

func (c *Chain) loadAccountStableBalance(addr proto.AccountAddress) (balance uint64, ok bool) {
c.RLock()
defer c.RUnlock()
return c.immutable.loadAccountStableBalance(addr)
return c.immutable.loadAccountTokenBalance(addr, tt)
}

func (c *Chain) loadSQLChainProfile(databaseID proto.DatabaseID) (profile *types.SQLChainProfile, ok bool) {
Expand Down
4 changes: 4 additions & 0 deletions blockproducer/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ var (
ErrBalanceOverflow = errors.New("balance overflow")
// ErrInsufficientBalance indicates that an account has insufficient balance for spending.
ErrInsufficientBalance = errors.New("insufficient balance")
// ErrInsufficientTransfer indicates that the transfer amount is insufficient for paying arrears.
ErrInsufficientTransfer = errors.New("insufficient transfer")
// ErrAccountNotFound indicates that an account is not found.
ErrAccountNotFound = errors.New("account not found")
// ErrAccountExists indicates that the an account already exists.
Expand All @@ -59,6 +61,8 @@ var (
ErrNoEnoughMiner = errors.New("can not get enough miners")
// ErrAccountPermissionDeny indicates that the sender does not own admin permission to the sqlchain.
ErrAccountPermissionDeny = errors.New("account permission deny")
// ErrNoAdminLeft indicates there is no admin user in sqlchain.
ErrNoAdminLeft = errors.New("no admin user left")
// ErrInvalidPermission indicates that the permission is invalid.
ErrInvalidPermission = errors.New("invalid permission")
// ErrMinerUserNotMatch indicates that the miner and user do not match.
Expand Down
153 changes: 108 additions & 45 deletions blockproducer/metastate.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,17 @@ func newMetaState() *metaState {
}

func (s *metaState) loadAccountObject(k proto.AccountAddress) (o *types.Account, loaded bool) {
if o, loaded = s.dirty.accounts[k]; loaded {
if o == nil {
var old *types.Account
if old, loaded = s.dirty.accounts[k]; loaded {
if old == nil {
loaded = false
return
}
o = deepcopy.Copy(old).(*types.Account)
return
}
if o, loaded = s.readonly.accounts[k]; loaded {
if old, loaded = s.readonly.accounts[k]; loaded {
o = deepcopy.Copy(old).(*types.Account)
return
}
return
Expand All @@ -92,43 +96,27 @@ func (s *metaState) loadOrStoreAccountObject(
return
}

func (s *metaState) loadAccountStableBalance(addr proto.AccountAddress) (b uint64, loaded bool) {
var o *types.Account
defer func() {
log.WithFields(log.Fields{
"account": addr.String(),
"balance": b,
"loaded": loaded,
}).Debug("queried stable account")
}()

if o, loaded = s.dirty.accounts[addr]; loaded && o != nil {
b = o.TokenBalance[types.Particle]
return
}
if o, loaded = s.readonly.accounts[addr]; loaded {
b = o.TokenBalance[types.Particle]
func (s *metaState) loadAccountTokenBalance(addr proto.AccountAddress,
tokenType types.TokenType) (b uint64, loaded bool) {
if !tokenType.Listed() {
return
}
return
}

func (s *metaState) loadAccountCovenantBalance(addr proto.AccountAddress) (b uint64, loaded bool) {
var o *types.Account
defer func() {
log.WithFields(log.Fields{
"account": addr.String(),
"balance": b,
"loaded": loaded,
}).Debug("queried covenant account")
"account": addr.String(),
"balance": b,
"tokenType": tokenType.String(),
"loaded": loaded,
}).Debug("queried token account")
}()

if o, loaded = s.dirty.accounts[addr]; loaded && o != nil {
b = o.TokenBalance[types.Wave]
b = o.TokenBalance[tokenType]
return
}
if o, loaded = s.readonly.accounts[addr]; loaded {
b = o.TokenBalance[types.Wave]
b = o.TokenBalance[tokenType]
return
}
return
Expand Down Expand Up @@ -275,7 +263,7 @@ func (s *metaState) increaseAccountToken(k proto.AccountAddress, amount uint64,
)
if dst, ok = s.dirty.accounts[k]; !ok {
if src, ok = s.readonly.accounts[k]; !ok {
err := errors.Wrap(ErrAccountNotFound, "increase stable balance fail")
err := errors.Wrap(ErrAccountNotFound, "increase account balance fail")
return err
}
dst = deepcopy.Copy(src).(*types.Account)
Expand All @@ -291,7 +279,7 @@ func (s *metaState) decreaseAccountToken(k proto.AccountAddress, amount uint64,
)
if dst, ok = s.dirty.accounts[k]; !ok {
if src, ok = s.readonly.accounts[k]; !ok {
err := errors.Wrap(ErrAccountNotFound, "increase stable balance fail")
err := errors.Wrap(ErrAccountNotFound, "decrease account balance fail")
return err
}
dst = deepcopy.Copy(src).(*types.Account)
Expand Down Expand Up @@ -322,6 +310,7 @@ func (s *metaState) transferAccountToken(transfer *types.Transfer) (err error) {
err = errors.Wrapf(ErrInvalidSender,
"applyTx failed: real sender %s, sender %s", realSender.String(), transfer.Sender.String())
log.WithError(err).Warning("public key not match sender in applyTransaction")
return
}

var (
Expand Down Expand Up @@ -882,10 +871,6 @@ func (s *metaState) updatePermission(tx *types.UpdatePermission) (err error) {
}).WithError(err).Error("unexpected err")
return
}
if sender == tx.TargetUser {
err = errors.Wrap(ErrInvalidSender, "user cannot update its permission by itself")
return
}
so, loaded := s.loadSQLChainObject(tx.TargetSQLChain.DatabaseID())
if !loaded {
log.WithFields(log.Fields{
Expand All @@ -903,9 +888,13 @@ func (s *metaState) updatePermission(tx *types.UpdatePermission) (err error) {

// check whether sender is admin and find targetUser
isAdmin := false
numOfAdmin := 0
targetUserIndex := -1
for i, u := range so.Users {
isAdmin = isAdmin || (sender == u.Address && u.Permission == types.Admin)
if u.Permission == types.Admin {
numOfAdmin++
}
if tx.TargetUser == u.Address {
targetUserIndex = i
}
Expand All @@ -919,12 +908,23 @@ func (s *metaState) updatePermission(tx *types.UpdatePermission) (err error) {
return ErrAccountPermissionDeny
}

// return error if number of Admin <= 1 and Admin want to revoke permission of itself
if numOfAdmin <= 1 && tx.TargetUser == sender && tx.Permission != types.Admin {
err = ErrNoAdminLeft
log.WithFields(log.Fields{
"sender": sender.String(),
"dbID": tx.TargetSQLChain.String(),
"targetUser": tx.TargetUser.String(),
}).WithError(err).Warning("in updatePermission")
return
}

// update targetUser's permission
if targetUserIndex == -1 {
u := types.SQLChainUser{
Address: tx.TargetUser,
Permission: tx.Permission,
Status: types.Normal,
Status: types.UnknownStatus,
}
so.Users = append(so.Users, &u)
} else {
Expand Down Expand Up @@ -998,7 +998,10 @@ func (s *metaState) updateBilling(tx *types.UpdateBilling) (err error) {
}
if !isMiner {
err = ErrInvalidSender
log.WithError(err).Warning("sender does not include in sqlchain (updateBilling)")
log.WithFields(log.Fields{
"miner_addr": minerAddr,
"miners": newProfile.Miners,
}).WithError(err).Warning("sender does not exists in sqlchain (updateBilling)")
return
}

Expand Down Expand Up @@ -1074,29 +1077,82 @@ func (s *metaState) transferSQLChainTokenBalance(transfer *types.Transfer) (err
realSender, err := crypto.PubKeyHash(transfer.Signee)
if err != nil {
err = errors.Wrap(err, "applyTx failed")
return err
return
}

if realSender != transfer.Sender {
err = errors.Wrapf(ErrInvalidSender,
"applyTx failed: real sender %s, sender %s", realSender.String(), transfer.Sender.String())
log.WithError(err).Warning("public key not match sender in applyTransaction")
return
}

var (
sqlchain *types.SQLChainProfile
account *types.Account
ok bool
)
sqlchain, ok = s.loadSQLChainObject(transfer.Sender.DatabaseID())
sqlchain, ok = s.loadSQLChainObject(transfer.Receiver.DatabaseID())
if !ok {
return ErrDatabaseNotFound
err = ErrDatabaseNotFound
log.WithFields(log.Fields{
"dbid": transfer.Receiver.DatabaseID(),
"sender": transfer.Sender.String(),
}).WithError(err).Warning("database not exist in transferSQLChainTokenBalance")
return
}
if sqlchain.TokenType != transfer.TokenType {
err = ErrWrongTokenType
log.WithFields(log.Fields{
"dbid": transfer.Receiver.DatabaseID(),
"sender": transfer.Sender.String(),
}).WithError(err).Warning("error token type in transferSQLChainTokenBalance")
return
}
account, ok = s.loadAccountObject(realSender)
if account.TokenBalance[transfer.TokenType] < transfer.Amount {
err = ErrInsufficientBalance
log.WithFields(log.Fields{
"addr": account.Address.String(),
"amount": account.TokenBalance[transfer.TokenType],
"transfer_amount": transfer.Amount,
"token_type": transfer.TokenType.String(),
}).WithError(err).Warning("in transferSQLChainTokenBalance")
return
}

for _, user := range sqlchain.Users {
if user.Address == transfer.Sender {
if sqlchain.TokenType != transfer.TokenType {
return ErrWrongTokenType
// process arrears
if user.Arrears > 0 {
if user.Arrears <= transfer.Amount {
for _, miner := range sqlchain.Miners {
newUserArrears := make([]*types.UserArrears, len(miner.UserArrears))
i := 0
for _, ua := range miner.UserArrears {
if ua.User == user.Address {
miner.PendingIncome += miner.UserArrears[i].Arrears
} else {
newUserArrears[i] = ua
i++
}
}
}
user.Arrears = 0
user.Status = types.Normal

transfer.Amount -= user.Arrears
account.TokenBalance[transfer.TokenType] -= user.Arrears
} else {
err = ErrInsufficientTransfer
log.WithFields(log.Fields{
"arrears": user.Arrears,
"transfer_amount": transfer.Amount,
}).WithError(err).Warning("in transferSQLChainTokenBalance")
return
}
}

minDep := minDeposit(sqlchain.GasPrice, uint64(len(sqlchain.Miners)))
if user.Deposit < minDep {
diff := minDep - user.Deposit
Expand All @@ -1105,15 +1161,22 @@ func (s *metaState) transferSQLChainTokenBalance(transfer *types.Transfer) (err
} else {
user.Deposit = minDep
diff2 := transfer.Amount - diff
user.Deposit += diff2
user.AdvancePayment += diff2
}
} else {
err = safeAdd(&user.AdvancePayment, &transfer.Amount)
if err != nil {
return err
return
}
}
account.TokenBalance[transfer.TokenType] -= transfer.Amount
if !user.Status.EnableQuery() {
if user.AdvancePayment > minDep {
user.Status = types.Normal
}
}
s.dirty.databases[transfer.Sender.DatabaseID()] = sqlchain
s.dirty.databases[transfer.Receiver.DatabaseID()] = sqlchain
s.dirty.accounts[realSender] = account
return
}
}
Expand Down
Loading