X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=wallet%2Fannotated.go;h=b6bf01654fcecc889a34a028923b9610f8d45e80;hp=fb9900fee64bde16b69d08c5525fc1b74a6727ff;hb=4bd838524ac21991ed954cc0e01c5729a63931ad;hpb=db158dcf09436b003defd333f1a665e7e051d820 diff --git a/wallet/annotated.go b/wallet/annotated.go index fb9900fe..b6bf0165 100644 --- a/wallet/annotated.go +++ b/wallet/annotated.go @@ -2,22 +2,18 @@ package wallet import ( "encoding/json" - "fmt" log "github.com/sirupsen/logrus" "github.com/vapor/account" "github.com/vapor/asset" "github.com/vapor/blockchain/query" - "github.com/vapor/blockchain/signers" "github.com/vapor/common" "github.com/vapor/consensus" "github.com/vapor/consensus/segwit" "github.com/vapor/crypto/sha3pool" - dbm "github.com/vapor/database/leveldb" "github.com/vapor/protocol/bc" "github.com/vapor/protocol/bc/types" - "github.com/vapor/protocol/vm/vmutil" ) // annotateTxs adds asset data to transactions @@ -35,29 +31,18 @@ func annotateTxsAsset(w *Wallet, txs []*query.AnnotatedTx) { } func (w *Wallet) getExternalDefinition(assetID *bc.AssetID) json.RawMessage { - definitionByte := w.DB.Get(asset.ExtAssetKey(assetID)) - if definitionByte == nil { - return nil + externalAsset, err := w.Store.GetAsset(assetID) + if err != nil && err != ErrGetAsset { + log.WithFields(log.Fields{"module": logModule, "err": err, "assetID": assetID.String()}).Info("fail on get asset definition.") } - - definitionMap := make(map[string]interface{}) - if err := json.Unmarshal(definitionByte, &definitionMap); err != nil { + if externalAsset == nil { return nil } - alias := assetID.String() - externalAsset := &asset.Asset{ - AssetID: *assetID, - Alias: &alias, - DefinitionMap: definitionMap, - RawDefinitionByte: definitionByte, - Signer: &signers.Signer{Type: "external"}, + if err := w.AssetReg.SaveAsset(externalAsset, *externalAsset.Alias); err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err, "assetAlias": *externalAsset.Alias}).Info("fail on save external asset to internal asset DB") } - - if err := w.AssetReg.SaveAsset(externalAsset, alias); err != nil { - log.WithFields(log.Fields{"module": logModule, "err": err, "assetID": alias}).Warning("fail on save external asset to internal asset DB") - } - return definitionByte + return json.RawMessage(externalAsset.RawDefinitionByte) } func (w *Wallet) getAliasDefinition(assetID bc.AssetID) (string, json.RawMessage) { @@ -85,14 +70,14 @@ func (w *Wallet) getAliasDefinition(assetID bc.AssetID) (string, json.RawMessage } // annotateTxs adds account data to transactions -func annotateTxsAccount(txs []*query.AnnotatedTx, walletDB dbm.DB) { +func (w *Wallet) annotateTxsAccount(txs []*query.AnnotatedTx) { for i, tx := range txs { for j, input := range tx.Inputs { //issue asset tx input SpentOutputID is nil if input.SpentOutputID == nil { continue } - localAccount, err := getAccountFromACP(input.ControlProgram, walletDB) + localAccount, err := w.getAccountFromACP(input.ControlProgram) if localAccount == nil || err != nil { continue } @@ -100,7 +85,7 @@ func annotateTxsAccount(txs []*query.AnnotatedTx, walletDB dbm.DB) { txs[i].Inputs[j].AccountID = localAccount.ID } for j, output := range tx.Outputs { - localAccount, err := getAccountFromACP(output.ControlProgram, walletDB) + localAccount, err := w.getAccountFromACP(output.ControlProgram) if localAccount == nil || err != nil { continue } @@ -110,42 +95,24 @@ func annotateTxsAccount(txs []*query.AnnotatedTx, walletDB dbm.DB) { } } -func getAccountFromACP(program []byte, walletDB dbm.DB) (*account.Account, error) { - var hash common.Hash - accountCP := account.CtrlProgram{} - localAccount := account.Account{} - +func (w *Wallet) getAccountFromACP(program []byte) (*account.Account, error) { + var hash [32]byte sha3pool.Sum256(hash[:], program) - - rawProgram := walletDB.Get(account.ContractKey(hash)) - if rawProgram == nil { - return nil, fmt.Errorf("failed get account control program:%x ", hash) - } - - if err := json.Unmarshal(rawProgram, &accountCP); err != nil { + accountCP, err := w.AccountMgr.GetControlProgram(bc.NewHash(hash)) + if err != nil { return nil, err } - accountValue := walletDB.Get(account.Key(accountCP.AccountID)) - if accountValue == nil { - return nil, fmt.Errorf("failed get account:%s ", accountCP.AccountID) - } - - if err := json.Unmarshal(accountValue, &localAccount); err != nil { + account, err := w.AccountMgr.FindByID(accountCP.AccountID) + if err != nil { return nil, err } - return &localAccount, nil + return account, nil } var emptyJSONObject = json.RawMessage(`{}`) -func isValidJSON(b []byte) bool { - var v interface{} - err := json.Unmarshal(b, &v) - return err == nil -} - func (w *Wallet) buildAnnotatedTransaction(orig *types.Tx, b *types.Block, statusFail bool, indexInBlock int) *query.AnnotatedTx { tx := &query.AnnotatedTx{ ID: orig.ID, @@ -177,32 +144,44 @@ func (w *Wallet) BuildAnnotatedInput(tx *types.Tx, i uint32) *query.AnnotatedInp if orig.InputType() != types.CoinbaseInputType { in.AssetID = orig.AssetID() in.Amount = orig.Amount() + } else { + in.AssetID = *consensus.BTMAssetID } id := tx.Tx.InputIDs[i] in.InputID = id e := tx.Entries[id] switch e := e.(type) { - case *bc.Spend: - in.Type = "spend" + case *bc.VetoInput: + in.Type = "veto" in.ControlProgram = orig.ControlProgram() - in.Address = w.getAddressFromControlProgram(in.ControlProgram) + in.Address = w.getAddressFromControlProgram(in.ControlProgram, false) in.SpentOutputID = e.SpentOutputId arguments := orig.Arguments() for _, arg := range arguments { in.WitnessArguments = append(in.WitnessArguments, arg) } - case *bc.Issuance: - in.Type = "issue" - in.IssuanceProgram = orig.IssuanceProgram() + + case *bc.CrossChainInput: + in.Type = "cross_chain_in" + in.ControlProgram = orig.ControlProgram() + in.Address = w.getAddressFromControlProgram(in.ControlProgram, true) + in.SpentOutputID = e.MainchainOutputId arguments := orig.Arguments() for _, arg := range arguments { in.WitnessArguments = append(in.WitnessArguments, arg) } - if assetDefinition := orig.AssetDefinition(); isValidJSON(assetDefinition) { - assetDefinition := json.RawMessage(assetDefinition) - in.AssetDefinition = &assetDefinition + + case *bc.Spend: + in.Type = "spend" + in.ControlProgram = orig.ControlProgram() + in.Address = w.getAddressFromControlProgram(in.ControlProgram, false) + in.SpentOutputID = e.SpentOutputId + arguments := orig.Arguments() + for _, arg := range arguments { + in.WitnessArguments = append(in.WitnessArguments, arg) } + case *bc.Coinbase: in.Type = "coinbase" in.Arbitrary = e.Arbitrary @@ -210,22 +189,27 @@ func (w *Wallet) BuildAnnotatedInput(tx *types.Tx, i uint32) *query.AnnotatedInp return in } -func (w *Wallet) getAddressFromControlProgram(prog []byte) string { +func (w *Wallet) getAddressFromControlProgram(prog []byte, isMainchain bool) string { + netParams := &consensus.ActiveNetParams + if isMainchain { + netParams = &consensus.BytomMainNetParams + } + if segwit.IsP2WPKHScript(prog) { if pubHash, err := segwit.GetHashFromStandardProg(prog); err == nil { - return buildP2PKHAddress(pubHash) + return BuildP2PKHAddress(pubHash, netParams) } } else if segwit.IsP2WSHScript(prog) { if scriptHash, err := segwit.GetHashFromStandardProg(prog); err == nil { - return buildP2SHAddress(scriptHash) + return BuildP2SHAddress(scriptHash, netParams) } } return "" } -func buildP2PKHAddress(pubHash []byte) string { - address, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams) +func BuildP2PKHAddress(pubHash []byte, netParams *consensus.Params) string { + address, err := common.NewAddressWitnessPubKeyHash(pubHash, netParams) if err != nil { return "" } @@ -233,8 +217,8 @@ func buildP2PKHAddress(pubHash []byte) string { return address.EncodeAddress() } -func buildP2SHAddress(scriptHash []byte) string { - address, err := common.NewAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams) +func BuildP2SHAddress(scriptHash []byte, netParams *consensus.Params) string { + address, err := common.NewAddressWitnessScriptHash(scriptHash, netParams) if err != nil { return "" } @@ -249,17 +233,28 @@ func (w *Wallet) BuildAnnotatedOutput(tx *types.Tx, idx int) *query.AnnotatedOut out := &query.AnnotatedOutput{ OutputID: *outid, Position: idx, - AssetID: *orig.AssetId, + AssetID: *orig.AssetAmount().AssetId, AssetDefinition: &emptyJSONObject, - Amount: orig.Amount, - ControlProgram: orig.ControlProgram, - Address: w.getAddressFromControlProgram(orig.ControlProgram), + Amount: orig.AssetAmount().Amount, + ControlProgram: orig.ControlProgram(), } - if vmutil.IsUnspendable(out.ControlProgram) { - out.Type = "retire" - } else { + var isMainchainAddress bool + switch e := tx.Entries[*outid].(type) { + case *bc.IntraChainOutput: out.Type = "control" + isMainchainAddress = false + + case *bc.CrossChainOutput: + out.Type = "cross_chain_out" + isMainchainAddress = true + + case *bc.VoteOutput: + out.Type = "vote" + out.Vote = e.Vote + isMainchainAddress = false } + + out.Address = w.getAddressFromControlProgram(orig.ControlProgram(), isMainchainAddress) return out }