Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions blockproducer/branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func newBranch(
}
inst.packed[k] = v
// Apply to preview
if err = inst.preview.apply(v); err != nil {
if err = inst.preview.apply(v, bn.height); err != nil {
return
}
}
Expand Down Expand Up @@ -154,7 +154,7 @@ func (b *branch) applyBlock(n *blockNode) (br *branch, err error) {
}
cpy.packed[k] = v
// Apply to preview
if err = cpy.preview.apply(v); err != nil {
if err = cpy.preview.apply(v, n.height); err != nil {
return
}
}
Expand Down Expand Up @@ -199,7 +199,7 @@ func (b *branch) produceBlock(
out := make([]pi.Transaction, 0, packCount)
for _, v := range txs {
var k = v.Hash()
if ierr = cpy.preview.apply(v); ierr != nil {
if ierr = cpy.preview.apply(v, h); ierr != nil {
continue
}
delete(cpy.unpacked, k)
Expand Down
4 changes: 2 additions & 2 deletions blockproducer/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func NewChainWithContext(ctx context.Context, cfg *Config) (c *Chain, err error)
if !existed {
var init = newMetaState()
for _, v := range cfg.Genesis.Transactions {
if ierr = init.apply(v); ierr != nil {
if ierr = init.apply(v, 0); ierr != nil {
err = errors.Wrap(ierr, "failed to initialize immutable state")
return
}
Expand Down Expand Up @@ -723,7 +723,7 @@ func (c *Chain) replaceAndSwitchToBranch(
for _, b := range newIrres {
txCount += b.txCount
for _, tx := range b.load().Transactions {
if err := c.immutable.apply(tx); err != nil {
if err := c.immutable.apply(tx, newBranch.head.height); err != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe b.height here?

log.WithError(err).Fatal("failed to apply block to immutable database")
}
delete(resultTxPool, tx.Hash()) // Remove confirmed transaction
Expand Down
46 changes: 44 additions & 2 deletions blockproducer/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
. "github.com/smartystreets/goconvey/convey"

pi "github.com/CovenantSQL/CovenantSQL/blockproducer/interfaces"
"github.com/CovenantSQL/CovenantSQL/conf"
"github.com/CovenantSQL/CovenantSQL/crypto"
"github.com/CovenantSQL/CovenantSQL/crypto/asymmetric"
"github.com/CovenantSQL/CovenantSQL/crypto/hash"
Expand Down Expand Up @@ -119,8 +120,10 @@ func TestChain(t *testing.T) {
},
Transactions: []pi.Transaction{
types.NewBaseAccount(&types.Account{
Address: addr1,
TokenBalance: [5]uint64{1000, 1000, 1000, 1000, 1000},
Address: addr1,
TokenBalance: [5]uint64{
1000000, 1000000, 1000000, 1000000, 1000000,
},
}),
},
}
Expand Down Expand Up @@ -302,6 +305,45 @@ func TestChain(t *testing.T) {
})
})

Convey("Multiple provide service", func() {
var (
nonce pi.AccountNonce
t1, t2 pi.Transaction
loaded bool
po1, po2 *types.ProviderProfile
bal1, bal2, bal3 uint64
)

// Create transaction for testing
bal1, loaded = chain.headBranch.preview.loadAccountTokenBalance(addr1, types.Particle)
So(loaded, ShouldBeTrue)
nonce, err = chain.nextNonce(addr1)
So(err, ShouldBeNil)
So(nonce, ShouldEqual, 1)
t1, err = newProvideService(nonce, priv1, addr1)
So(err, ShouldBeNil)
t2, err = newProvideService(nonce+1, priv1, addr1)
So(err, ShouldBeNil)
err = chain.storeTx(t1)
So(err, ShouldBeNil)
err = chain.produceBlock(begin.Add(chain.period * conf.BPHeightCIPFixProvideService).UTC())
So(err, ShouldBeNil)
bal2, loaded = chain.headBranch.preview.loadAccountTokenBalance(addr1, types.Particle)
So(loaded, ShouldBeTrue)
po1, loaded = chain.headBranch.preview.loadProviderObject(addr1)
So(loaded, ShouldBeTrue)
So(bal1-bal2, ShouldEqual, po1.Deposit)
err = chain.storeTx(t2)
So(err, ShouldBeNil)
err = chain.produceBlock(begin.Add(chain.period * (conf.BPHeightCIPFixProvideService + 1)).UTC())
So(err, ShouldBeNil)
bal3, loaded = chain.headBranch.preview.loadAccountTokenBalance(addr1, types.Particle)
So(bal3, ShouldEqual, bal2)
po2, loaded = chain.headBranch.preview.loadProviderObject(addr1)
So(po2, ShouldResemble, po1)
So(po2 == po1, ShouldBeFalse)
})

Convey("When transfer transactions are added", func() {
var (
nonce pi.AccountNonce
Expand Down
25 changes: 19 additions & 6 deletions blockproducer/metastate.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,13 +509,26 @@ func (s *metaState) increaseNonce(addr proto.AccountAddress) (err error) {
return
}

func (s *metaState) updateProviderList(tx *types.ProvideService) (err error) {
func (s *metaState) updateProviderList(tx *types.ProvideService, height uint32) (err error) {
sender, err := crypto.PubKeyHash(tx.Signee)
if err != nil {
err = errors.Wrap(err, "updateProviderList failed")
return
}

if height >= conf.BPHeightCIPFixProvideService {
// load previous provider object
po, loaded := s.loadProviderObject(sender)
if loaded {
// refund
if err = s.increaseAccountStableBalance(sender, po.Deposit); err != nil {
return
}

s.deleteProviderObject(sender)
}
}

// deposit
var (
minDeposit = conf.GConf.MinProviderDeposit
Expand Down Expand Up @@ -1113,7 +1126,7 @@ func (s *metaState) transferSQLChainTokenBalance(transfer *types.Transfer) (err
return
}

func (s *metaState) applyTransaction(tx pi.Transaction) (err error) {
func (s *metaState) applyTransaction(tx pi.Transaction, height uint32) (err error) {
switch t := tx.(type) {
case *types.Transfer:
err = s.transferSQLChainTokenBalance(t)
Expand All @@ -1124,7 +1137,7 @@ func (s *metaState) applyTransaction(tx pi.Transaction) (err error) {
case *types.BaseAccount:
err = s.storeBaseAccount(t.Address, &t.Account)
case *types.ProvideService:
err = s.updateProviderList(t)
err = s.updateProviderList(t, height)
case *types.CreateDatabase:
err = s.matchProvidersWithUser(t)
case *types.UpdatePermission:
Expand All @@ -1135,7 +1148,7 @@ func (s *metaState) applyTransaction(tx pi.Transaction) (err error) {
err = s.updateBilling(t)
case *pi.TransactionWrapper:
// call again using unwrapped transaction
err = s.applyTransaction(t.Unwrap())
err = s.applyTransaction(t.Unwrap(), height)
default:
err = ErrUnknownTransactionType
}
Expand All @@ -1159,7 +1172,7 @@ func (s *metaState) generateGenesisBlock(dbID proto.DatabaseID, tx *types.Create
return
}

func (s *metaState) apply(t pi.Transaction) (err error) {
func (s *metaState) apply(t pi.Transaction, height uint32) (err error) {
log.Infof("get tx: %s", t.GetTransactionType())
// NOTE(leventeliu): bypass pool in this method.
var (
Expand All @@ -1184,7 +1197,7 @@ func (s *metaState) apply(t pi.Transaction) (err error) {
return
}
// Try to apply transaction to metaState
if err = s.applyTransaction(t); err != nil {
if err = s.applyTransaction(t, height); err != nil {
log.WithError(err).Debug("apply transaction failed")
return
}
Expand Down
Loading