OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / claim / rpc / bytom / bytom_main_tx.go
diff --git a/claim/rpc/bytom/bytom_main_tx.go b/claim/rpc/bytom/bytom_main_tx.go
deleted file mode 100644 (file)
index 344d111..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-package bytom
-
-import (
-       "bytes"
-       "crypto/hmac"
-       "crypto/sha256"
-       "encoding/json"
-       "time"
-
-       log "github.com/sirupsen/logrus"
-
-       "github.com/vapor/account"
-       "github.com/vapor/blockchain/txbuilder"
-       "github.com/vapor/claim/bytom/mainchain"
-       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
-       "github.com/vapor/claim/rpc"
-       "github.com/vapor/common"
-       "github.com/vapor/consensus"
-       "github.com/vapor/crypto/ed25519/chainkd"
-       chainjson "github.com/vapor/encoding/json"
-       "github.com/vapor/equity/pegin_contract"
-       "github.com/vapor/errors"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       "github.com/vapor/protocol/vm/vmutil"
-)
-
-type BytomMainTx struct {
-       rpc.MainTxParam
-}
-
-func (b *BytomMainTx) BuildMainChainTxForContract() ([]byte, error) {
-       var xpubs []chainkd.XPub
-       for _, pub := range b.Pubs {
-               xpub := chainkd.XPub{}
-               if err := xpub.UnmarshalText([]byte(pub)); err != nil {
-                       return nil, err
-               }
-               // pub + scriptPubKey 生成一个随机数A
-               var tmp [32]byte
-               h := hmac.New(sha256.New, xpub[:])
-               h.Write(b.ClaimScript)
-               tweak := h.Sum(tmp[:])
-               // pub +  A 生成一个新的公钥pub_new
-               chaildXPub := xpub.Child(tweak)
-               xpubs = append(xpubs, chaildXPub)
-       }
-
-       utxo := &account.UTXO{}
-       if err := json.Unmarshal([]byte(b.Utxo), utxo); err != nil {
-               return nil, err
-       }
-       txInput, sigInst, err := contractToInputs(utxo, xpubs, b.ClaimScript)
-       builder := mainchain.NewBuilder(time.Now())
-       builder.AddInput(txInput, sigInst)
-       changeAmount := uint64(0)
-       retire := false
-       tx := &types.Tx{}
-       if err := tx.UnmarshalText([]byte(b.Tx)); err != nil {
-               return nil, err
-       }
-       for _, key := range tx.GetResultIds() {
-               output, err := tx.Retire(*key)
-               if err != nil {
-                       log.WithFields(log.Fields{"moudle": "transact", "err": err}).Warn("buildMainChainTx error")
-                       continue
-               }
-               retire = true
-               var controlProgram []byte
-               retBool := true
-               if controlProgram, retBool = getInput(tx.Entries, *key, b.ControlProgram); !retBool {
-                       return nil, errors.New("The corresponding input cannot be found")
-               }
-
-               assetID := *output.Source.Value.AssetId
-               out := bytomtypes.NewTxOutput(assetID, output.Source.Value.Amount, controlProgram)
-               builder.AddOutput(out)
-               changeAmount = utxo.Amount - output.Source.Value.Amount
-       }
-
-       if !retire {
-               return nil, errors.New("It's not a transaction to retire assets")
-       }
-
-       if changeAmount > 100000000 {
-               u := utxo
-               out := bytomtypes.NewTxOutput(u.AssetID, changeAmount, utxo.ControlProgram)
-               builder.AddOutput(out)
-       }
-
-       tmpl, txData, err := builder.Build()
-       if err != nil {
-               return nil, err
-       }
-
-       for i, out := range tmpl.Transaction.Outputs {
-               if bytes.Equal(out.ControlProgram, utxo.ControlProgram) {
-                       if changeAmount-100000000 > 0 {
-                               txData.Outputs[i].Amount = changeAmount - 100000000
-                       }
-               }
-       }
-       tmpl.Transaction = bytomtypes.NewTx(*txData)
-       resp, err := mainchain.MarshalText(tmpl)
-       if err != nil {
-               return nil, err
-       }
-       return resp, nil
-}
-
-func (b *BytomMainTx) BuildMainChainTx() ([]byte, error) {
-       var xpubs []chainkd.XPub
-       for _, pub := range b.Pubs {
-
-               xpub := chainkd.XPub{}
-               if err := xpub.UnmarshalText([]byte(pub)); err != nil {
-                       return nil, err
-               }
-               // pub + scriptPubKey 生成一个随机数A
-               var tmp [32]byte
-               h := hmac.New(sha256.New, xpub[:])
-               h.Write(b.ClaimScript)
-               tweak := h.Sum(tmp[:])
-               // pub +  A 生成一个新的公钥pub_new
-               chaildXPub := xpub.Child(tweak)
-               xpubs = append(xpubs, chaildXPub)
-       }
-
-       utxo := &account.UTXO{}
-       if err := json.Unmarshal([]byte(b.Utxo), utxo); err != nil {
-               return nil, err
-       }
-
-       txInput, sigInst, err := utxoToInputs(xpubs, utxo)
-       if err != nil {
-               return nil, err
-       }
-
-       builder := mainchain.NewBuilder(time.Now())
-       builder.AddInput(txInput, sigInst)
-       changeAmount := uint64(0)
-       retire := false
-       tx := &types.Tx{}
-       if err := tx.UnmarshalText([]byte(b.Tx)); err != nil {
-               return nil, err
-       }
-       for _, key := range tx.GetResultIds() {
-               output, err := tx.Retire(*key)
-               if err != nil {
-                       log.WithFields(log.Fields{"moudle": "transact", "err": err}).Warn("buildMainChainTx error")
-                       continue
-               }
-               retire = true
-               var controlProgram []byte
-               retBool := true
-               if controlProgram, retBool = getInput(tx.Entries, *key, b.ControlProgram); !retBool {
-                       return nil, errors.New("The corresponding input cannot be found")
-               }
-
-               assetID := *output.Source.Value.AssetId
-               out := bytomtypes.NewTxOutput(assetID, output.Source.Value.Amount, controlProgram)
-               builder.AddOutput(out)
-               changeAmount = utxo.Amount - output.Source.Value.Amount
-
-       }
-
-       if !retire {
-               return nil, errors.New("It's not a transaction to retire assets")
-       }
-
-       if changeAmount > 0 {
-               u := utxo
-               out := bytomtypes.NewTxOutput(u.AssetID, changeAmount, utxo.ControlProgram)
-               builder.AddOutput(out)
-       }
-
-       tmpl, txData, err := builder.Build()
-       if err != nil {
-               return nil, err
-       }
-       /*
-               //交易费估算
-               txGasResp, err := EstimateTxGasForMainchain(*tmpl)
-               if err != nil {
-                       return nil, err
-               }
-       */
-       for i, out := range tmpl.Transaction.Outputs {
-               if bytes.Equal(out.ControlProgram, utxo.ControlProgram) {
-                       //tx.Outputs[i].Amount = changeAmount - uint64(txGasResp.TotalNeu)
-                       tx.Outputs[i].Amount = changeAmount - 100000000
-               }
-       }
-       tmpl.Transaction = bytomtypes.NewTx(*txData)
-       resp, err := json.Marshal(tmpl)
-
-       if err != nil {
-               return nil, err
-       }
-
-       return resp, nil
-}
-
-type BytomMainSign struct {
-       rpc.MainTxSignParam
-}
-
-func (b *BytomMainSign) SignWithKey() (interface{}, error) {
-       xprv := &chainkd.XPrv{}
-       if err := xprv.UnmarshalText([]byte(b.Xprv)); err != nil {
-               return nil, err
-       }
-
-       xpub := &chainkd.XPub{}
-       if err := xpub.UnmarshalText([]byte(b.XPub)); err != nil {
-               return nil, err
-       }
-
-       // pub + scriptPubKey 生成一个随机数A
-       var tmp [32]byte
-       h := hmac.New(sha256.New, xpub[:])
-       h.Write(b.ClaimScript)
-       tweak := h.Sum(tmp[:])
-       // pub +  A 生成一个新的公钥pub_new
-       privateKey := xprv.Child(tweak, false)
-
-       txs := &mainchain.Template{}
-       if err := mainchain.UnmarshalText([]byte(b.Txs), txs); err != nil {
-               return nil, err
-       }
-
-       if err := sign(txs, privateKey); err != nil {
-               return nil, err
-       }
-       log.Info("Sign Transaction complete.")
-       return struct {
-               Tx           *mainchain.Template `json:"transaction"`
-               SignComplete bool                `json:"sign_complete"`
-       }{Tx: txs, SignComplete: mainchain.SignProgress(txs)}, nil
-}
-
-func sign(tmpl *mainchain.Template, xprv chainkd.XPrv) error {
-       for i, sigInst := range tmpl.SigningInstructions {
-               for j, wc := range sigInst.WitnessComponents {
-                       switch sw := wc.(type) {
-                       case *mainchain.SignatureWitness:
-                               err := sw.Sign(tmpl, uint32(i), xprv)
-                               if err != nil {
-                                       return errors.WithDetailf(err, "adding signature(s) to signature witness component %d of input %d", j, i)
-                               }
-                       case *mainchain.RawTxSigWitness:
-                               err := sw.Sign(tmpl, uint32(i), xprv)
-                               if err != nil {
-                                       return errors.WithDetailf(err, "adding signature(s) to raw-signature witness component %d of input %d", j, i)
-                               }
-                       }
-               }
-       }
-       return materializeWitnesses(tmpl)
-}
-
-func materializeWitnesses(txTemplate *mainchain.Template) error {
-       msg := txTemplate.Transaction
-
-       if msg == nil {
-               return errors.Wrap(txbuilder.ErrMissingRawTx)
-       }
-
-       if len(txTemplate.SigningInstructions) > len(msg.Inputs) {
-               return errors.Wrap(txbuilder.ErrBadInstructionCount)
-       }
-
-       for i, sigInst := range txTemplate.SigningInstructions {
-               if msg.Inputs[sigInst.Position] == nil {
-                       return errors.WithDetailf(txbuilder.ErrBadTxInputIdx, "signing instruction %d references missing tx input %d", i, sigInst.Position)
-               }
-
-               var witness [][]byte
-               for j, wc := range sigInst.WitnessComponents {
-                       err := wc.Materialize(&witness)
-                       if err != nil {
-                               return errors.WithDetailf(err, "error in witness component %d of input %d", j, i)
-                       }
-               }
-               msg.SetInputArguments(sigInst.Position, witness)
-       }
-
-       return nil
-}
-
-//
-func getInput(entry map[bc.Hash]bc.Entry, outputID bc.Hash, controlProgram string) ([]byte, bool) {
-       output := entry[outputID].(*bc.Retirement)
-       mux := entry[*output.Source.Ref].(*bc.Mux)
-
-       for _, valueSource := range mux.GetSources() {
-               spend := entry[*valueSource.Ref].(*bc.Spend)
-               prevout := entry[*spend.SpentOutputId].(*bc.Output)
-
-               var ctrlProgram chainjson.HexBytes
-               ctrlProgram = prevout.ControlProgram.Code
-               tmp, _ := ctrlProgram.MarshalText()
-               if string(tmp) == controlProgram {
-                       return ctrlProgram, true
-               }
-       }
-       return nil, false
-}
-
-// UtxoToInputs convert an utxo to the txinput
-func utxoToInputs(xpubs []chainkd.XPub, u *account.UTXO) (*bytomtypes.TxInput, *mainchain.SigningInstruction, error) {
-       txInput := bytomtypes.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
-       sigInst := &mainchain.SigningInstruction{}
-       quorum := len(xpubs)
-       if u.Address == "" {
-               sigInst.AddWitnessKeys(xpubs, quorum)
-               return txInput, sigInst, nil
-       }
-
-       address, err := common.DecodeBytomAddress(u.Address, &consensus.ActiveNetParams)
-       if err != nil {
-               return nil, nil, err
-       }
-
-       sigInst.AddRawWitnessKeysWithoutPath(xpubs, quorum)
-
-       switch address.(type) {
-       case *common.AddressWitnessPubKeyHash:
-               derivedPK := xpubs[0].PublicKey()
-               sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness([]byte(derivedPK)))
-
-       case *common.AddressWitnessScriptHash:
-               derivedXPubs := xpubs
-               derivedPKs := chainkd.XPubKeys(derivedXPubs)
-               script, err := vmutil.P2SPMultiSigProgram(derivedPKs, quorum)
-               if err != nil {
-                       return nil, nil, err
-               }
-               sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness(script))
-
-       default:
-               return nil, nil, errors.New("unsupport address type")
-       }
-
-       return txInput, sigInst, nil
-}
-
-func contractToInputs(u *account.UTXO, xpubs []chainkd.XPub, ClaimScript chainjson.HexBytes) (*bytomtypes.TxInput, *mainchain.SigningInstruction, error) {
-       txInput := bytomtypes.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
-       sigInst := &mainchain.SigningInstruction{}
-
-       // raw_tx_signature
-       for _, xpub := range xpubs {
-               xpubsTmp := []chainkd.XPub{xpub}
-               sigInst.AddRawWitnessKeysWithoutPath(xpubsTmp, 1)
-       }
-
-       // data
-       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(ClaimScript)
-       if err != nil {
-               return nil, nil, err
-       }
-       sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness(peginContractPrograms))
-
-       return txInput, sigInst, nil
-}