Unverified Commit 1eda55a1 authored by Paladz's avatar Paladz Committed by GitHub

Merge pull request #1699 from Bytom/dev

Dev
parents 0e46e1f0 eab3a1dc
......@@ -10,10 +10,9 @@ import (
"strings"
"time"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/crypto/sha3pool"
"github.com/bytom/errors"
dbm "github.com/bytom/database/leveldb"
)
const tokenSize = 32
......
......@@ -6,9 +6,8 @@ import (
"strings"
"testing"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/errors"
dbm "github.com/bytom/database/leveldb"
)
func TestCreate(t *testing.T) {
......
......@@ -10,7 +10,6 @@ import (
"github.com/golang/groupcache/lru"
log "github.com/sirupsen/logrus"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/blockchain/signers"
"github.com/bytom/blockchain/txbuilder"
......@@ -24,6 +23,7 @@ import (
"github.com/bytom/protocol"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/vm/vmutil"
dbm "github.com/bytom/database/leveldb"
)
const (
......@@ -47,16 +47,16 @@ var (
// pre-define errors for supporting bytom errorFormatter
var (
ErrDuplicateAlias = errors.New("duplicate account alias")
ErrDuplicateIndex = errors.New("duplicate account with same xPubs and index")
ErrFindAccount = errors.New("fail to find account")
ErrMarshalAccount = errors.New("failed marshal account")
ErrInvalidAddress = errors.New("invalid address")
ErrFindCtrlProgram = errors.New("fail to find account control program")
ErrDeriveRule = errors.New("invalid key derive rule")
ErrContractIndex = errors.New("exceed the maximum addresses per account")
ErrAccountIndex = errors.New("exceed the maximum accounts per xpub")
ErrFindTransaction = errors.New("no transaction")
ErrDuplicateAlias = errors.New("Duplicate account alias")
ErrDuplicateIndex = errors.New("Duplicate account with same xPubs and index")
ErrFindAccount = errors.New("Failed to find account")
ErrMarshalAccount = errors.New("Failed to marshal account")
ErrInvalidAddress = errors.New("Invalid address")
ErrFindCtrlProgram = errors.New("Failed to find account control program")
ErrDeriveRule = errors.New("Invalid key derivation rule")
ErrContractIndex = errors.New("Exceeded maximum addresses per account")
ErrAccountIndex = errors.New("Exceeded maximum accounts per xpub")
ErrFindTransaction = errors.New("No transaction")
)
// ContractKey account control promgram store prefix
......
......@@ -7,16 +7,15 @@ import (
"strings"
"testing"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/blockchain/pseudohsm"
"github.com/bytom/blockchain/signers"
"github.com/bytom/crypto/ed25519/chainkd"
"github.com/bytom/database/leveldb"
"github.com/bytom/database"
"github.com/bytom/errors"
"github.com/bytom/event"
"github.com/bytom/protocol"
"github.com/bytom/testutil"
dbm "github.com/bytom/database/leveldb"
)
func TestCreateAccountWithUppercase(t *testing.T) {
......@@ -215,7 +214,7 @@ func mockAccountManager(t *testing.T) *Manager {
testDB := dbm.NewDB("testdb", "memdb", dirPath)
dispatcher := event.NewDispatcher()
store := leveldb.NewStore(testDB)
store := database.NewStore(testDB)
txPool := protocol.NewTxPool(store, dispatcher)
chain, err := protocol.NewChain(store, txPool)
if err != nil {
......
......@@ -9,10 +9,10 @@ import (
"time"
log "github.com/sirupsen/logrus"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/errors"
"github.com/bytom/protocol/bc"
dbm "github.com/bytom/database/leveldb"
)
const desireUtxoCount = 5
......
......@@ -6,10 +6,9 @@ import (
"testing"
"time"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/protocol/bc"
"github.com/bytom/testutil"
dbm "github.com/bytom/database/leveldb"
)
func TestAddUnconfirmedUtxo(t *testing.T) {
......
This diff is collapsed.
......@@ -17,12 +17,14 @@ func (a *API) createAsset(ctx context.Context, ins struct {
RootXPubs []chainkd.XPub `json:"root_xpubs"`
Quorum int `json:"quorum"`
Definition map[string]interface{} `json:"definition"`
LimitHeight int64 `json:"limit_height"`
IssuanceProgram chainjson.HexBytes `json:"issuance_program"`
}) Response {
ass, err := a.wallet.AssetReg.Define(
ins.RootXPubs,
ins.Quorum,
ins.Definition,
ins.LimitHeight,
strings.ToUpper(strings.TrimSpace(ins.Alias)),
ins.IssuanceProgram,
)
......
......@@ -59,17 +59,17 @@ var respErrFormatter = map[error]httperror.Info{
account.ErrInsufficient: {400, "BTM700", "Funds of account are insufficient"},
account.ErrImmature: {400, "BTM701", "Available funds of account are immature"},
account.ErrReserved: {400, "BTM702", "Available UTXOs of account have been reserved"},
account.ErrMatchUTXO: {400, "BTM703", "Not found UTXO with given hash"},
account.ErrMatchUTXO: {400, "BTM703", "UTXO with given hash not found"},
ErrBadActionType: {400, "BTM704", "Invalid action type"},
ErrBadAction: {400, "BTM705", "Invalid action object"},
ErrBadActionConstruction: {400, "BTM706", "Invalid action construction"},
txbuilder.ErrMissingFields: {400, "BTM707", "One or more fields are missing"},
txbuilder.ErrBadAmount: {400, "BTM708", "Invalid asset amount"},
account.ErrFindAccount: {400, "BTM709", "Not found account"},
asset.ErrFindAsset: {400, "BTM710", "Not found asset"},
account.ErrFindAccount: {400, "BTM709", "Account not found"},
asset.ErrFindAsset: {400, "BTM710", "Asset not found"},
txbuilder.ErrBadContractArgType: {400, "BTM711", "Invalid contract argument type"},
txbuilder.ErrOrphanTx: {400, "BTM712", "Not found transaction input utxo"},
txbuilder.ErrExtTxFee: {400, "BTM713", "Transaction fee exceed max limit"},
txbuilder.ErrOrphanTx: {400, "BTM712", "Transaction input UTXO not found"},
txbuilder.ErrExtTxFee: {400, "BTM713", "Transaction fee exceeded max limit"},
txbuilder.ErrNoGasInput: {400, "BTM714", "Transaction has no gas input"},
// Submit transaction error namespace (73x ~ 79x)
......
......@@ -8,6 +8,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/bytom/account"
"github.com/bytom/asset"
"github.com/bytom/blockchain/query"
"github.com/bytom/blockchain/signers"
"github.com/bytom/blockchain/txbuilder"
......@@ -52,13 +53,17 @@ func (a *API) listAccounts(ctx context.Context, filter struct {
func (a *API) getAsset(ctx context.Context, filter struct {
ID string `json:"id"`
}) Response {
asset, err := a.wallet.AssetReg.GetAsset(filter.ID)
ass, err := a.wallet.AssetReg.GetAsset(filter.ID)
if err != nil {
log.Errorf("getAsset: %v", err)
return NewErrorResponse(err)
}
return NewSuccessResponse(asset)
annotatedAsset, err := asset.Annotated(ass)
if err != nil {
return NewErrorResponse(err)
}
return NewSuccessResponse(annotatedAsset)
}
// POST /list-assets
......@@ -71,7 +76,15 @@ func (a *API) listAssets(ctx context.Context, filter struct {
return NewErrorResponse(err)
}
return NewSuccessResponse(assets)
annotatedAssets := []*query.AnnotatedAsset{}
for _, ass := range assets {
annotatedAsset, err := asset.Annotated(ass)
if err != nil {
return NewErrorResponse(err)
}
annotatedAssets = append(annotatedAssets, annotatedAsset)
}
return NewSuccessResponse(annotatedAssets)
}
// POST /list-balances
......
......@@ -3,7 +3,6 @@ package api
import (
"context"
"encoding/json"
"math"
"strings"
"time"
......@@ -11,10 +10,7 @@ import (
"github.com/bytom/account"
"github.com/bytom/blockchain/txbuilder"
"github.com/bytom/consensus"
"github.com/bytom/consensus/segwit"
"github.com/bytom/errors"
"github.com/bytom/math/checked"
"github.com/bytom/net/http/reqid"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
......@@ -23,7 +19,6 @@ import (
var (
defaultTxTTL = 30 * time.Minute
defaultBaseRate = float64(100000)
flexibleGas = int64(1800)
)
func (a *API) actionDecoder(action string) (func([]byte) (txbuilder.Action, error), bool) {
......@@ -223,115 +218,11 @@ func (a *API) submitTxs(ctx context.Context, ins struct {
return NewSuccessResponse(&submitTxsResp{TxID: txHashs})
}
// EstimateTxGasResp estimate transaction consumed gas
type EstimateTxGasResp struct {
TotalNeu int64 `json:"total_neu"`
StorageNeu int64 `json:"storage_neu"`
VMNeu int64 `json:"vm_neu"`
}
// EstimateTxGas estimate consumed neu for transaction
func EstimateTxGas(template txbuilder.Template) (*EstimateTxGasResp, error) {
// base tx size and not include sign
data, err := template.Transaction.TxData.MarshalText()
if err != nil {
return nil, err
}
baseTxSize := int64(len(data))
// extra tx size for sign witness parts
signSize := estimateSignSize(template.SigningInstructions)
// total gas for tx storage
totalTxSizeGas, ok := checked.MulInt64(baseTxSize+signSize, consensus.StorageGasRate)
if !ok {
return nil, errors.New("calculate txsize gas got a math error")
}
// consume gas for run VM
totalP2WPKHGas := int64(0)
totalP2WSHGas := int64(0)
baseP2WPKHGas := int64(1419)
// flexible Gas is used for handle need extra utxo situation
for pos, inpID := range template.Transaction.Tx.InputIDs {
sp, err := template.Transaction.Spend(inpID)
if err != nil {
continue
}
resOut, err := template.Transaction.Output(*sp.SpentOutputId)
if err != nil {
continue
}
if segwit.IsP2WPKHScript(resOut.ControlProgram.Code) {
totalP2WPKHGas += baseP2WPKHGas
} else if segwit.IsP2WSHScript(resOut.ControlProgram.Code) {
sigInst := template.SigningInstructions[pos]
totalP2WSHGas += estimateP2WSHGas(sigInst)
}
}
// total estimate gas
totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas + flexibleGas
// rounding totalNeu with base rate 100000
totalNeu := float64(totalGas*consensus.VMGasRate) / defaultBaseRate
roundingNeu := math.Ceil(totalNeu)
estimateNeu := int64(roundingNeu) * int64(defaultBaseRate)
// TODO add priority
return &EstimateTxGasResp{
TotalNeu: estimateNeu,
StorageNeu: totalTxSizeGas * consensus.VMGasRate,
VMNeu: (totalP2WPKHGas + totalP2WSHGas) * consensus.VMGasRate,
}, nil
}
// estimate p2wsh gas.
// OP_CHECKMULTISIG consume (984 * a - 72 * b - 63) gas,
// where a represent the num of public keys, and b represent the num of quorum.
func estimateP2WSHGas(sigInst *txbuilder.SigningInstruction) int64 {
P2WSHGas := int64(0)
baseP2WSHGas := int64(738)
for _, witness := range sigInst.WitnessComponents {
switch t := witness.(type) {
case *txbuilder.SignatureWitness:
P2WSHGas += baseP2WSHGas + (984*int64(len(t.Keys)) - 72*int64(t.Quorum) - 63)
case *txbuilder.RawTxSigWitness:
P2WSHGas += baseP2WSHGas + (984*int64(len(t.Keys)) - 72*int64(t.Quorum) - 63)
}
}
return P2WSHGas
}
// estimate signature part size.
// if need multi-sign, calculate the size according to the length of keys.
func estimateSignSize(signingInstructions []*txbuilder.SigningInstruction) int64 {
signSize := int64(0)
baseWitnessSize := int64(300)
for _, sigInst := range signingInstructions {
for _, witness := range sigInst.WitnessComponents {
switch t := witness.(type) {
case *txbuilder.SignatureWitness:
signSize += int64(t.Quorum) * baseWitnessSize
case *txbuilder.RawTxSigWitness:
signSize += int64(t.Quorum) * baseWitnessSize
}
}
}
return signSize
}
// POST /estimate-transaction-gas
func (a *API) estimateTxGas(ctx context.Context, in struct {
TxTemplate txbuilder.Template `json:"transaction_template"`
}) Response {
txGasResp, err := EstimateTxGas(in.TxTemplate)
txGasResp, err := txbuilder.EstimateTxGas(in.TxTemplate)
if err != nil {
return NewErrorResponse(err)
}
......
......@@ -4,7 +4,6 @@ import (
"encoding/json"
"github.com/bytom/blockchain/query"
"github.com/bytom/blockchain/signers"
chainjson "github.com/bytom/encoding/json"
"github.com/bytom/protocol/vm/vmutil"
)
......@@ -25,40 +24,23 @@ func Annotated(a *Asset) (*query.AnnotatedAsset, error) {
jsonDefinition = json.RawMessage(a.RawDefinitionByte)
}
aa := &query.AnnotatedAsset{
ID: a.AssetID,
Definition: &jsonDefinition,
IssuanceProgram: chainjson.HexBytes(a.IssuanceProgram),
}
if a.Alias != nil {
aa.Alias = *a.Alias
annotatedAsset := &query.AnnotatedAsset{
ID: a.AssetID,
Alias: *a.Alias,
RawDefinitionByte: a.RawDefinitionByte,
Definition: &jsonDefinition,
IssuanceProgram: chainjson.HexBytes(a.IssuanceProgram),
}
annotatedAsset.LimitHeight, _ = vmutil.GetIssuanceProgramRestrictHeight(a.IssuanceProgram)
if a.Signer != nil {
path := signers.GetBip0032Path(a.Signer, signers.AssetKeySpace)
var jsonPath []chainjson.HexBytes
for _, p := range path {
jsonPath = append(jsonPath, p)
}
for _, xpub := range a.Signer.XPubs {
derived := xpub.Derive(path)
aa.Keys = append(aa.Keys, &query.AssetKey{
RootXPub: xpub,
AssetPubkey: derived[:],
AssetDerivationPath: jsonPath,
})
}
aa.Quorum = a.Signer.Quorum
} else {
pubkeys, quorum, err := vmutil.ParseP2SPMultiSigProgram(a.IssuanceProgram)
if err == nil {
for _, pubkey := range pubkeys {
pubkey := pubkey
aa.Keys = append(aa.Keys, &query.AssetKey{
AssetPubkey: chainjson.HexBytes(pubkey[:]),
})
}
aa.Quorum = quorum
annotatedAsset.AnnotatedSigner = query.AnnotatedSigner{
Type: a.Signer.Type,
XPubs: a.Signer.XPubs,
Quorum: a.Signer.Quorum,
KeyIndex: a.Signer.KeyIndex,
DeriveRule: a.Signer.DeriveRule,
}
}
return aa, nil
return annotatedAsset, nil
}
......@@ -7,7 +7,6 @@ import (
"sync"
"github.com/golang/groupcache/lru"
dbm "github.com/tendermint/tmlibs/db"
"golang.org/x/crypto/sha3"
"github.com/bytom/blockchain/signers"
......@@ -15,6 +14,7 @@ import (
"github.com/bytom/consensus"
"github.com/bytom/crypto/ed25519"
"github.com/bytom/crypto/ed25519/chainkd"
dbm "github.com/bytom/database/leveldb"
chainjson "github.com/bytom/encoding/json"
"github.com/bytom/errors"
"github.com/bytom/protocol"
......@@ -126,7 +126,7 @@ func (reg *Registry) getNextAssetIndex() uint64 {
}
// Define defines a new Asset.
func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[string]interface{}, alias string, issuanceProgram chainjson.HexBytes) (*Asset, error) {
func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[string]interface{}, limitHeight int64, alias string, issuanceProgram chainjson.HexBytes) (*Asset, error) {
var err error
var assetSigner *signers.Signer
......@@ -159,7 +159,7 @@ func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[str
path := signers.GetBip0032Path(assetSigner, signers.AssetKeySpace)
derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, path)
derivedPKs := chainkd.XPubKeys(derivedXPubs)
issuanceProgram, vmver, err = multisigIssuanceProgram(derivedPKs, assetSigner.Quorum)
issuanceProgram, vmver, err = multisigIssuanceProgram(derivedPKs, assetSigner.Quorum, limitHeight)
if err != nil {
return nil, err
}
......@@ -363,8 +363,8 @@ func serializeAssetDef(def map[string]interface{}) ([]byte, error) {
return json.MarshalIndent(def, "", " ")
}
func multisigIssuanceProgram(pubkeys []ed25519.PublicKey, nrequired int) (program []byte, vmversion uint64, err error) {
issuanceProg, err := vmutil.P2SPMultiSigProgram(pubkeys, nrequired)
func multisigIssuanceProgram(pubkeys []ed25519.PublicKey, nrequired int, blockHeight int64) (program []byte, vmversion uint64, err error) {
issuanceProg, err := vmutil.P2SPMultiSigProgramWithHeight(pubkeys, nrequired, blockHeight)
if err != nil {
return nil, 0, err
}
......
......@@ -9,11 +9,10 @@ import (
"strings"
"testing"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/consensus"
"github.com/bytom/crypto/ed25519/chainkd"
"github.com/bytom/database/leveldb"
"github.com/bytom/database"
dbm "github.com/bytom/database/leveldb"
"github.com/bytom/event"
"github.com/bytom/protocol"
"github.com/bytom/testutil"
......@@ -22,7 +21,7 @@ import (
func TestDefineAssetWithLowercase(t *testing.T) {
reg := mockNewRegistry(t)
alias := "lower"
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, alias, nil)
if err != nil {
t.Fatal(err)
}
......@@ -34,7 +33,7 @@ func TestDefineAssetWithLowercase(t *testing.T) {
func TestDefineAssetWithSpaceTrimed(t *testing.T) {
reg := mockNewRegistry(t)
alias := " WITH SPACE "
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, alias, nil)
if err != nil {
t.Fatal(err)
}
......@@ -46,24 +45,32 @@ func TestDefineAssetWithSpaceTrimed(t *testing.T) {
func TestDefineAsset(t *testing.T) {
ctx := context.Background()
reg := mockNewRegistry(t)
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, "asset-alias", nil)
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, "asset-alias", nil)
if err != nil {
testutil.FatalErr(t, err)
}
found, err := reg.FindByID(ctx, &asset.AssetID)
limitAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 100, "limit-asset", nil)
if err != nil {
t.Errorf("unexpected error %v", err)
testutil.FatalErr(t, err)
}
if !testutil.DeepEqual(asset, found) {
t.Errorf("expected asset %v to be recorded as %v", asset, found)
assets := []*Asset{asset, limitAsset}
for _, ass := range assets {
found, err := reg.FindByID(ctx, &ass.AssetID)
if err != nil {
t.Errorf("unexpected error %v", err)
}
if !testutil.DeepEqual(ass, found) {
t.Errorf("expected asset %v to be recorded as %v", ass, found)
}
}
}
func TestDefineBtmAsset(t *testing.T) {
reg := mockNewRegistry(t)
_, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, consensus.BTMAlias, nil)
_, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, consensus.BTMAlias, nil)
if err == nil {
testutil.FatalErr(t, err)
}
......@@ -73,7 +80,7 @@ func TestFindAssetByID(t *testing.T) {
ctx := context.Background()
reg := mockNewRegistry(t)
keys := []chainkd.XPub{testutil.TestXPub}
asset, err := reg.Define(keys, 1, nil, "TESTASSET", nil)
asset, err := reg.Define(keys, 1, nil, 0, "TESTASSET", nil)
if err != nil {
testutil.FatalErr(t, err)
......@@ -94,7 +101,7 @@ func TestUpdateAssetAlias(t *testing.T) {
oldAlias := "OLD_ALIAS"
newAlias := "NEW_ALIAS"
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, oldAlias, nil)
asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, oldAlias, nil)
if err != nil {
testutil.FatalErr(t, err)
}
......@@ -128,12 +135,12 @@ func TestListAssets(t *testing.T) {
firstAlias := "FIRST_ALIAS"
secondAlias := "SECOND_ALIAS"
firstAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, firstAlias, nil)
firstAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, firstAlias, nil)
if err != nil {
testutil.FatalErr(t, err)
}
secondAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, secondAlias, nil)
secondAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, secondAlias, nil)
if err != nil {
testutil.FatalErr(t, err)
}
......@@ -152,7 +159,7 @@ func TestListAssets(t *testing.T) {
}
func mockChain(testDB dbm.DB) (*protocol.Chain, error) {
store := leveldb.NewStore(testDB)
store := database.NewStore(testDB)
dispatcher := event.NewDispatcher()
txPool := protocol.NewTxPool(store, dispatcher)
chain, err := protocol.NewChain(store, txPool)
......
......@@ -68,19 +68,23 @@ type AnnotatedAccount struct {
//AnnotatedAsset means an annotated asset.
type AnnotatedAsset struct {
ID bc.AssetID `json:"id"`
Alias string `json:"alias,omitempty"`
IssuanceProgram chainjson.HexBytes `json:"issuance_program"`
Keys []*AssetKey `json:"keys"`
Quorum int `json:"quorum"`
Definition *json.RawMessage `json:"definition"`
AnnotatedSigner
ID bc.AssetID `json:"id"`
Alias string `json:"alias"`
VMVersion uint64 `json:"vm_version"`
IssuanceProgram chainjson.HexBytes `json:"issue_program"`
RawDefinitionByte chainjson.HexBytes `json:"raw_definition_byte"`
Definition *json.RawMessage `json:"definition"`
LimitHeight int64 `json:"limit_height"`
}
//AssetKey means an asset key.
type AssetKey struct {
RootXPub chainkd.XPub `json:"root_xpub"`
AssetPubkey chainjson.HexBytes `json:"asset_pubkey"`
AssetDerivationPath []chainjson.HexBytes `json:"asset_derivation_path"`
//AnnotatedSigner means an annotated signer for asset.
type AnnotatedSigner struct {
Type string `json:"type"`
XPubs []chainkd.XPub `json:"xpubs"`
Quorum int `json:"quorum"`
KeyIndex uint64 `json:"key_index"`
DeriveRule uint8 `json:"derive_rule"`
}
//AnnotatedUTXO means an annotated utxo.
......
package txbuilder
import (
"github.com/bytom/consensus"
"github.com/bytom/consensus/segwit"
"github.com/bytom/protocol/bc/types"
"github.com/bytom/protocol/vm/vmutil"
)