"github.com/jinzhu/gorm"
log "github.com/sirupsen/logrus"
- vaporCfg "github.com/vapor/config"
"github.com/vapor/errors"
"github.com/vapor/federation/common"
"github.com/vapor/federation/config"
"github.com/vapor/federation/database"
"github.com/vapor/federation/database/orm"
"github.com/vapor/federation/service"
+ "github.com/vapor/federation/util"
"github.com/vapor/protocol/bc"
)
-var fedProg = vaporCfg.FederationProgrom(vaporCfg.CommonConfig)
-
type mainchainKeeper struct {
cfg *config.Chain
db *gorm.DB
node *service.Node
chainName string
- assetCache *database.AssetCache
+ assetStore *database.AssetStore
+ fedProg []byte
}
-func NewMainchainKeeper(db *gorm.DB, chainCfg *config.Chain) *mainchainKeeper {
+func NewMainchainKeeper(db *gorm.DB, assetStore *database.AssetStore, cfg *config.Config) *mainchainKeeper {
return &mainchainKeeper{
- cfg: chainCfg,
+ cfg: &cfg.Mainchain,
db: db,
- node: service.NewNode(chainCfg.Upstream),
- chainName: chainCfg.Name,
- assetCache: database.NewAssetCache(),
+ node: service.NewNode(cfg.Mainchain.Upstream),
+ chainName: cfg.Mainchain.Name,
+ assetStore: assetStore,
+ fedProg: util.SegWitWrap(util.ParseFedProg(cfg.Warders, cfg.Quorum)),
}
}
func (m *mainchainKeeper) tryAttachBlock(chain *orm.Chain, block *types.Block, txStatus *bc.TransactionStatus) error {
blockHash := block.Hash()
log.WithFields(log.Fields{"block_height": block.Height, "block_hash": blockHash.String()}).Info("start to attachBlock")
- m.db.Begin()
+ dbTx := m.db.Begin()
if err := m.processBlock(chain, block, txStatus); err != nil {
- m.db.Rollback()
+ dbTx.Rollback()
return err
}
- return m.db.Commit().Error
+ return dbTx.Commit().Error
}
func (m *mainchainKeeper) processBlock(chain *orm.Chain, block *types.Block, txStatus *bc.TransactionStatus) error {
func (m *mainchainKeeper) isDepositTx(tx *types.Tx) bool {
for _, output := range tx.Outputs {
- if bytes.Equal(output.OutputCommitment.ControlProgram, fedProg) {
+ if bytes.Equal(output.OutputCommitment.ControlProgram, m.fedProg) {
return true
}
}
func (m *mainchainKeeper) isWithdrawalTx(tx *types.Tx) bool {
for _, input := range tx.Inputs {
- if bytes.Equal(input.ControlProgram(), fedProg) {
+ if bytes.Equal(input.ControlProgram(), m.fedProg) {
return true
}
}
func (m *mainchainKeeper) getCrossChainReqs(crossTransactionID uint64, tx *types.Tx, statusFail bool) ([]*orm.CrossTransactionReq, error) {
// assume inputs are from an identical owner
script := hex.EncodeToString(tx.Inputs[0].ControlProgram())
- inputs := []*orm.CrossTransactionReq{}
+ reqs := []*orm.CrossTransactionReq{}
for i, rawOutput := range tx.Outputs {
// check valid deposit
- if !bytes.Equal(rawOutput.OutputCommitment.ControlProgram, fedProg) {
+ if !bytes.Equal(rawOutput.OutputCommitment.ControlProgram, m.fedProg) {
continue
}
continue
}
- asset, err := m.getAsset(rawOutput.OutputCommitment.AssetAmount.AssetId.String())
+ asset, err := m.assetStore.GetByAssetID(rawOutput.OutputCommitment.AssetAmount.AssetId.String())
if err != nil {
return nil, err
}
- input := &orm.CrossTransactionReq{
+ req := &orm.CrossTransactionReq{
CrossTransactionID: crossTransactionID,
SourcePos: uint64(i),
AssetID: asset.ID,
AssetAmount: rawOutput.OutputCommitment.AssetAmount.Amount,
Script: script,
}
- inputs = append(inputs, input)
+ reqs = append(reqs, req)
}
- return inputs, nil
+ return reqs, nil
}
func (m *mainchainKeeper) processWithdrawalTx(chain *orm.Chain, block *types.Block, txIndex uint64, tx *types.Tx) error {
stmt := m.db.Model(&orm.CrossTransaction{}).Where("chain_id != ?", chain.ID).
Where(&orm.CrossTransaction{
DestTxHash: sql.NullString{tx.ID.String(), true},
- Status: common.CrossTxSubmittedStatus,
+ Status: common.CrossTxPendingStatus,
}).UpdateColumn(&orm.CrossTransaction{
DestBlockHeight: sql.NullInt64{int64(block.Height), true},
DestBlockHash: sql.NullString{blockHash.String(), true},
switch inp := input.TypedInput.(type) {
case *types.IssuanceInput:
assetID := inp.AssetID()
- if _, err := m.getAsset(assetID.String()); err == nil {
+ if _, err := m.assetStore.GetByAssetID(assetID.String()); err == nil {
continue
}
- asset := &orm.Asset{
+ m.assetStore.Add(&orm.Asset{
AssetID: assetID.String(),
IssuanceProgram: hex.EncodeToString(inp.IssuanceProgram),
VMVersion: inp.VMVersion,
RawDefinitionByte: hex.EncodeToString(inp.AssetDefinition),
- }
- if err := m.db.Create(asset).Error; err != nil {
- return err
- }
-
- m.assetCache.Add(asset.AssetID, asset)
+ })
}
}
}
return nil
}
-
-func (m *mainchainKeeper) getAsset(assetID string) (*orm.Asset, error) {
- if asset := m.assetCache.Get(assetID); asset != nil {
- return asset, nil
- }
-
- asset := &orm.Asset{AssetID: assetID}
- if err := m.db.Where(asset).First(asset).Error; err != nil {
- return nil, errors.Wrap(err, "asset not found in memory and mysql")
- }
-
- m.assetCache.Add(assetID, asset)
- return asset, nil
-}