Skip to content

Commit

Permalink
allow contract asset transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
elvis88 authored and erickyan86 committed Nov 20, 2019
1 parent 8ec91f9 commit 5acd4c7
Show file tree
Hide file tree
Showing 21 changed files with 312 additions and 83 deletions.
10 changes: 5 additions & 5 deletions accountmanager/accountmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -1338,12 +1338,12 @@ func (am *AccountManager) IssueAsset(fromName common.Name, asset IssueAsset, num
}

//IncAsset2Acct increase asset and add amount to accout balance
func (am *AccountManager) IncAsset2Acct(fromName common.Name, toName common.Name, assetID uint64, amount *big.Int) error {
func (am *AccountManager) IncAsset2Acct(fromName common.Name, toName common.Name, assetID uint64, amount *big.Int, forkID uint64) error {
if err := am.ast.CheckOwner(fromName, assetID); err != nil {
return err
}

if err := am.ast.IncreaseAsset(fromName, assetID, amount); err != nil {
if err := am.ast.IncreaseAsset(fromName, assetID, amount, forkID); err != nil {
return err
}
return nil
Expand All @@ -1366,7 +1366,7 @@ func (am *AccountManager) process(accountManagerContext *types.AccountManagerCon
var fromAccountExtra []common.Name
fromAccountExtra = append(fromAccountExtra, accountManagerContext.FromAccountExtra...)

if err := action.Check(accountManagerContext.ChainConfig); err != nil {
if err := action.Check(curForkID, accountManagerContext.ChainConfig); err != nil {
return nil, err
}

Expand Down Expand Up @@ -1459,7 +1459,7 @@ func (am *AccountManager) process(accountManagerContext *types.AccountManagerCon
return nil, ErrNegativeAmount
}

if err := am.IncAsset2Acct(action.Sender(), inc.To, inc.AssetID, inc.Amount); err != nil {
if err := am.IncAsset2Acct(action.Sender(), inc.To, inc.AssetID, inc.Amount, curForkID); err != nil {
return nil, err
}

Expand Down Expand Up @@ -1509,7 +1509,7 @@ func (am *AccountManager) process(accountManagerContext *types.AccountManagerCon
return nil, err
}

if err := am.ast.UpdateAsset(action.Sender(), asset.AssetID, asset.Founder); err != nil {
if err := am.ast.UpdateAsset(action.Sender(), asset.AssetID, asset.Founder, curForkID); err != nil {
return nil, err
}
case types.SetAssetOwner:
Expand Down
2 changes: 1 addition & 1 deletion accountmanager/accountmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1455,7 +1455,7 @@ func TestAccountManager_IncAsset2Acct(t *testing.T) {
sdb: tt.fields.sdb,
ast: tt.fields.ast,
}
if err := am.IncAsset2Acct(tt.args.fromName, tt.args.toName, tt.args.AssetID, tt.args.amount); (err != nil) != tt.wantErr {
if err := am.IncAsset2Acct(tt.args.fromName, tt.args.toName, tt.args.AssetID, tt.args.amount, 4); (err != nil) != tt.wantErr {
t.Errorf("%q. AccountManager.IncAsset2Acct() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
}
Expand Down
27 changes: 23 additions & 4 deletions asset/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"strconv"
"strings"

"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/log"
"github.com/fractalplatform/fractal/common"
"github.com/fractalplatform/fractal/params"
Expand Down Expand Up @@ -294,6 +295,11 @@ func (a *Asset) IssueAssetObject(ao *AssetObject) (uint64, error) {

//IssueAsset issue asset
func (a *Asset) IssueAsset(assetName string, number uint64, forkID uint64, symbol string, amount *big.Int, dec uint64, founder common.Name, owner common.Name, limit *big.Int, contract common.Name, description string) (uint64, error) {
if forkID >= params.ForkID4 {
if amount.Cmp(math.MaxBig256) > 0 {
return 0, ErrAmountOverMax256
}
}
_, err := a.GetAssetIDByName(assetName)
if err != nil && err != ErrAssetNotExist {
return 0, err
Expand Down Expand Up @@ -355,7 +361,7 @@ func (a *Asset) DestroyAsset(accountName common.Name, assetID uint64, amount *bi
}

//IncreaseAsset increase asset, upperlimit == 0 means no upper limit
func (a *Asset) IncreaseAsset(accountName common.Name, assetID uint64, amount *big.Int) error {
func (a *Asset) IncreaseAsset(accountName common.Name, assetID uint64, amount *big.Int, forkID uint64) error {
if accountName == "" {
return ErrAccountNameNull
}
Expand All @@ -372,6 +378,11 @@ func (a *Asset) IncreaseAsset(accountName common.Name, assetID uint64, amount *b
if asset == nil {
return ErrAssetNotExist
}
if forkID >= params.ForkID4 {
if (new(big.Int).Add(asset.GetAssetAmount(), amount)).Cmp(math.MaxBig256) > 0 {
return ErrAmountOverMax256
}
}
// if asset.GetAssetOwner() != accountName {
// return ErrOwnerMismatch
// }
Expand All @@ -398,7 +409,7 @@ func (a *Asset) IncreaseAsset(accountName common.Name, assetID uint64, amount *b
}

//UpdateAsset change asset info
func (a *Asset) UpdateAsset(accountName common.Name, assetID uint64, founderName common.Name) error {
func (a *Asset) UpdateAsset(accountName common.Name, assetID uint64, founderName common.Name, curForkID uint64) error {
if accountName == "" {
return ErrAccountNameNull
}
Expand All @@ -412,8 +423,16 @@ func (a *Asset) UpdateAsset(accountName common.Name, assetID uint64, founderName
// if asset.GetAssetOwner() != accountName {
// return ErrOwnerMismatch
// }

asset.SetAssetFounder(founderName)
if curForkID >= params.ForkID4 {
if len(founderName.String()) == 0 {
assetOwner := asset.GetAssetOwner()
asset.SetAssetFounder(assetOwner)
} else {
asset.SetAssetFounder(founderName)
}
} else {
asset.SetAssetFounder(founderName)
}
return a.SetAssetObject(asset)
}

Expand Down
17 changes: 10 additions & 7 deletions asset/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ func TestAsset_IncreaseAsset(t *testing.T) {
a := &Asset{
sdb: tt.fields.sdb,
}
if err := a.IncreaseAsset(tt.args.accountName, tt.args.AssetID, tt.args.amount); (err != nil) != tt.wantErr {
if err := a.IncreaseAsset(tt.args.accountName, tt.args.AssetID, tt.args.amount, 4); (err != nil) != tt.wantErr {
t.Errorf("%q. Asset.IncreaseAsset() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
}
Expand Down Expand Up @@ -501,6 +501,7 @@ func TestAsset_UpdateAsset(t *testing.T) {
AssetID uint64
Owner common.Name
founder common.Name
forkID uint64
}
tests := []struct {
name string
Expand All @@ -509,17 +510,19 @@ func TestAsset_UpdateAsset(t *testing.T) {
wantErr bool
}{
// TODO: Add test cases
{"nilname", fields{assetDB}, args{common.Name(""), 1, common.Name(""), common.Name("")}, true},
{"wrongAssetID", fields{assetDB}, args{common.Name("11"), 0, common.Name(""), common.Name("")}, false},
{"wrongamount", fields{assetDB}, args{common.Name("11"), 123, common.Name(""), common.Name("")}, true},
{"nilfounder", fields{assetDB}, args{common.Name("a123456789afff"), 1, common.Name("a123456789aeee"), common.Name("")}, false},
{"normal", fields{assetDB}, args{common.Name("a123456789afff"), 1, common.Name("a123456789afff"), common.Name("a123456789afff")}, false},
{"nilname", fields{assetDB}, args{common.Name(""), 1, common.Name(""), common.Name(""), 0}, true},
{"wrongAssetID", fields{assetDB}, args{common.Name("11"), 0, common.Name(""), common.Name(""), 0}, false},
{"wrongamount", fields{assetDB}, args{common.Name("11"), 123, common.Name(""), common.Name(""), 0}, true},
{"nilfounder", fields{assetDB}, args{common.Name("a123456789afff"), 1, common.Name("a123456789aeee"), common.Name(""), 0}, false},
{"nilfounder", fields{assetDB}, args{common.Name("a123456789afff"), 1, common.Name("a123456789aeee"), common.Name(""), 4}, false},
{"nilfounder", fields{assetDB}, args{common.Name("a123456789afff"), 1, common.Name("a123456789aeee"), common.Name("a123456789afff"), 4}, false},
{"normal", fields{assetDB}, args{common.Name("a123456789afff"), 1, common.Name("a123456789afff"), common.Name("a123456789afff"), 0}, false},
}
for _, tt := range tests {
a := &Asset{
sdb: tt.fields.sdb,
}
if err := a.UpdateAsset(tt.args.accountName, tt.args.AssetID, tt.args.founder); (err != nil) != tt.wantErr {
if err := a.UpdateAsset(tt.args.accountName, tt.args.AssetID, tt.args.founder, tt.args.forkID); (err != nil) != tt.wantErr {
t.Errorf("%q. Asset.updateAsset() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
}
Expand Down
1 change: 1 addition & 0 deletions asset/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ var (
ErrAssetManagerNotExist = errors.New("asset manager name not exist")
ErrDetailTooLong = errors.New("detail info exceed maximum")
ErrNegativeAmount = errors.New("negative amount")
ErrAmountOverMax256 = errors.New("amount over max uint256")
)
3 changes: 3 additions & 0 deletions common/pubkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,6 @@ func (p *PubKey) UnmarshalJSON(input []byte) error {
func (p PubKey) Compare(x PubKey) int {
return bytes.Compare(p.Bytes(), x.Bytes())
}

// EmptyPubKey empty
var EmptyPubKey PubKey
7 changes: 6 additions & 1 deletion consensus/dpos/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"math/big"
"strings"

"github.com/fractalplatform/fractal/common"
"github.com/fractalplatform/fractal/types"
)

Expand Down Expand Up @@ -54,9 +55,11 @@ type IDB interface {
GetTakeOver() (uint64, error)

Undelegate(string, *big.Int) (*types.Action, error)
IncAsset2Acct(string, string, *big.Int) (*types.Action, error)
IncAsset2Acct(string, string, *big.Int, uint64) (*types.Action, error)
GetBalanceByTime(name string, timestamp uint64) (*big.Int, error)
GetCandidateInfoByTime(epoch uint64, name string, timestamp uint64) (*CandidateInfo, error)

CanMine(name string, pub []byte) error
}

// CandidateType candidate status
Expand Down Expand Up @@ -137,6 +140,7 @@ type CandidateInfo struct {
Type CandidateType `json:"type"`
PrevKey string `json:"-"`
NextKey string `json:"-"`
PubKey common.PubKey `json:"pubkey" rlp:"-"`
}

func (candidateInfo *CandidateInfo) copy() *CandidateInfo {
Expand All @@ -150,6 +154,7 @@ func (candidateInfo *CandidateInfo) copy() *CandidateInfo {
Counter: candidateInfo.Counter,
ActualCounter: candidateInfo.ActualCounter,
Type: candidateInfo.Type,
PubKey: candidateInfo.PubKey,
}
}

Expand Down
20 changes: 8 additions & 12 deletions consensus/dpos/dpos.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,20 @@ func (s *stateDB) Undelegate(to string, amount *big.Int) (*types.Action, error)
}
return action, accountDB.TransferAsset(common.StrToName(s.name), common.StrToName(to), s.assetid, amount)
}
func (s *stateDB) IncAsset2Acct(from string, to string, amount *big.Int) (*types.Action, error) {
func (s *stateDB) IncAsset2Acct(from string, to string, amount *big.Int, forkID uint64) (*types.Action, error) {
action := types.NewAction(types.IncreaseAsset, common.StrToName(s.name), common.StrToName(to), 0, s.assetid, 0, amount, nil, nil)
accountDB, err := accountmanager.NewAccountManager(s.state)
if err != nil {
return action, err
}
return action, accountDB.IncAsset2Acct(common.StrToName(from), common.StrToName(to), s.assetid, amount)
return action, accountDB.IncAsset2Acct(common.StrToName(from), common.StrToName(to), s.assetid, amount, forkID)
}
func (s *stateDB) IsValidSign(name string, pubkey []byte) bool {
func (s *stateDB) IsValidSign(name string, pubkey []byte) error {
accountDB, err := accountmanager.NewAccountManager(s.state)
if err != nil {
return false
return err
}
return accountDB.IsValidSign(common.StrToName(name), common.BytesToPubKey(pubkey)) == nil
return accountDB.IsValidSign(common.StrToName(name), common.BytesToPubKey(pubkey))
}
func (s *stateDB) GetBalanceByTime(name string, timestamp uint64) (*big.Int, error) {
accountDB, err := accountmanager.NewAccountManager(s.state)
Expand Down Expand Up @@ -531,7 +531,7 @@ func (dpos *Dpos) finalize0(chain consensus.IChainReader, header *types.Header,
counter := int64(0)
extraReward := new(big.Int).Mul(dpos.config.extraBlockReward(), big.NewInt(counter))
reward := new(big.Int).Add(dpos.config.blockReward(), extraReward)
sys.IncAsset2Acct(dpos.config.SystemName, header.Coinbase.String(), reward)
sys.IncAsset2Acct(dpos.config.SystemName, header.Coinbase.String(), reward, header.CurForkID())

blk := types.NewBlock(header, txs, receipts)

Expand Down Expand Up @@ -689,7 +689,7 @@ func (dpos *Dpos) finalize1(chain consensus.IChainReader, header *types.Header,
extraCounter := int64(0)
extraReward := new(big.Int).Mul(dpos.config.extraBlockReward(), big.NewInt(extraCounter))
reward := new(big.Int).Add(dpos.config.blockReward(), extraReward)
sys.IncAsset2Acct(dpos.config.SystemName, header.Coinbase.String(), reward)
sys.IncAsset2Acct(dpos.config.SystemName, header.Coinbase.String(), reward, header.CurForkID())

blk := types.NewBlock(header, txs, receipts)
// first hard fork at a specific number
Expand Down Expand Up @@ -1002,13 +1002,9 @@ func (dpos *Dpos) IsValidateCandidate(chain consensus.IChainReader, parent *type
return fmt.Errorf("%v %v, except %v %v(%v) index %v (%v epoch) ", errInvalidBlockCandidate, candidate, tname, pstate.ActivatedCandidateSchedule, pstate.UsingCandidateIndexSchedule, offset, pstate.Epoch)
}

db := &stateDB{
name: dpos.config.AccountName,
state: state,
}
has := false
for _, pubkey := range pubkeys {
if db.IsValidSign(candidate, pubkey) {
if sys.CanMine(candidate, pubkey) == nil {
has = true
}
}
Expand Down
46 changes: 44 additions & 2 deletions consensus/dpos/ldb.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
package dpos

import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"math/big"
"strings"

"github.com/fractalplatform/fractal/common"
"github.com/fractalplatform/fractal/types"
"github.com/fractalplatform/fractal/utils/rlp"
)
Expand All @@ -34,9 +36,9 @@ type IDatabase interface {
Delete(key string) error

Undelegate(string, *big.Int) (*types.Action, error)
IncAsset2Acct(string, string, *big.Int) (*types.Action, error)
IncAsset2Acct(string, string, *big.Int, uint64) (*types.Action, error)
GetBalanceByTime(name string, timestamp uint64) (*big.Int, error)

IsValidSign(name string, pubkey []byte) error
GetSnapshot(key string, timestamp uint64) ([]byte, error)
}

Expand All @@ -48,6 +50,9 @@ var (
// ActivatedCandidateKeyPrefix candidateInfo
ActivatedCandidateKeyPrefix = "ap"

// CandidatePubKeyPrefix candidateInfo
CandidatePubKeyPrefix = "pk"

// VoterKeyPrefix voterInfo
VoterKeyPrefix = "v"
// VoterHead head
Expand Down Expand Up @@ -80,6 +85,20 @@ func NewLDB(db IDatabase) (*LDB, error) {
return ldb, nil
}

// CanMine allow mining block
func (db *LDB) CanMine(name string, pub []byte) error {
pubkey := strings.Join([]string{CandidatePubKeyPrefix, fmt.Sprintf("%s", name)}, Separator)
if val, _ := db.Get(pubkey); val != nil {
if bytes.Compare(common.EmptyPubKey.Bytes(), val) != 0 {
if bytes.Compare(pub, val) == 0 {
return nil
}
return fmt.Errorf("need pubkey %s", common.BytesToPubKey(val).String())
}
}
return db.IsValidSign(name, pub)
}

// SetCandidate update candidate info
func (db *LDB) SetCandidate(candidate *CandidateInfo) error {
if candidate.Name != CandidateHead && len(candidate.PrevKey) == 0 && len(candidate.NextKey) == 0 {
Expand Down Expand Up @@ -119,6 +138,18 @@ func (db *LDB) SetCandidate(candidate *CandidateInfo) error {
} else if err := db.Put(key, val); err != nil {
return err
}

if common.EmptyPubKey.Compare(candidate.PubKey) != 0 {
pubkey := strings.Join([]string{CandidatePubKeyPrefix, fmt.Sprintf("%s", candidate.Name)}, Separator)
if err := db.Put(pubkey, candidate.PubKey.Bytes()); err != nil {
return err
}
} else {
pubkey := strings.Join([]string{CandidatePubKeyPrefix, fmt.Sprintf("%s", candidate.Name)}, Separator)
if err := db.Delete(pubkey); err != nil {
return err
}
}
return nil
}

Expand Down Expand Up @@ -155,6 +186,11 @@ func (db *LDB) DelCandidate(epoch uint64, name string) error {
if err := db.Delete(key); err != nil {
return err
}
pubkey := strings.Join([]string{CandidatePubKeyPrefix, fmt.Sprintf("%s", name)}, Separator)
if err := db.Delete(pubkey); err != nil {
return err
}

head, err := db.GetCandidate(epoch, CandidateHead)
if err != nil {
return err
Expand All @@ -174,6 +210,12 @@ func (db *LDB) GetCandidate(epoch uint64, name string) (*CandidateInfo, error) {
} else if err := rlp.DecodeBytes(val, candidateInfo); err != nil {
return nil, err
}

pubkey := strings.Join([]string{CandidatePubKeyPrefix, fmt.Sprintf("%s", name)}, Separator)
if val, _ := db.Get(pubkey); val != nil {
candidateInfo.PubKey.SetBytes(val)
}

return candidateInfo, nil
}

Expand Down
7 changes: 6 additions & 1 deletion consensus/dpos/ldb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (ldb *levelDB) Delegate(string, *big.Int) error {
func (ldb *levelDB) Undelegate(string, *big.Int) (*types.Action, error) {
return nil, nil
}
func (ldb *levelDB) IncAsset2Acct(string, string, *big.Int) (*types.Action, error) {
func (ldb *levelDB) IncAsset2Acct(string, string, *big.Int, uint64) (*types.Action, error) {
return nil, nil
}
func (ldb *levelDB) GetSnapshot(string, uint64) ([]byte, error) {
Expand All @@ -70,6 +70,11 @@ func (ldb *levelDB) GetSnapshot(string, uint64) ([]byte, error) {
func (ldb *levelDB) GetBalanceByTime(name string, timestamp uint64) (*big.Int, error) {
return new(big.Int).Mul(big.NewInt(1000000000), DefaultConfig.decimals()), nil
}

func (ldb *levelDB) IsValidSign(name string, pubkey []byte) error {
return nil
}

func newTestLDB() (*levelDB, func()) {
dirname, err := ioutil.TempDir(os.TempDir(), "dpos_test_")
if err != nil {
Expand Down
Loading

0 comments on commit 5acd4c7

Please sign in to comment.