Commit 1fc2b758 authored by Paladz's avatar Paladz Committed by GitHub

Merge pull request #1730 from Bytom/prod

Prod
parents d2815dfc 7f08c11f
......@@ -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
......
This diff is collapsed.
......@@ -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)
......
......@@ -85,7 +85,7 @@ func (a *API) submitBlock(ctx context.Context, req *SubmitBlockReq) Response {
return NewErrorResponse(errors.New("block submitted is orphan"))
}
if err = a.eventDispatcher.Post(event.NewMinedBlockEvent{Block: req.Block}); err != nil {
if err = a.eventDispatcher.Post(event.NewMinedBlockEvent{Block: *req.Block}); err != nil {
return NewErrorResponse(err)
}
......
......@@ -144,9 +144,10 @@ func (a *API) listTransactions(ctx context.Context, filter struct {
transaction, err = a.wallet.GetTransactionByTxID(filter.ID)
if err != nil && filter.Unconfirmed {
transaction, err = a.wallet.GetUnconfirmedTxByTxID(filter.ID)
if err != nil {
return NewErrorResponse(err)
}
}
if err != nil {
return NewErrorResponse(err)
}
transactions = []*query.AnnotatedTx{transaction}
} else {
......
......@@ -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)
}
......
......@@ -27,12 +27,13 @@ func Annotated(a *Asset) (*query.AnnotatedAsset, error) {
annotatedAsset := &query.AnnotatedAsset{
ID: a.AssetID,
Alias: *a.Alias,
VMVersion: a.VMVersion,
RawDefinitionByte: a.RawDefinitionByte,
Definition: &jsonDefinition,
IssuanceProgram: chainjson.HexBytes(a.IssuanceProgram),
}
annotatedAsset.LimitHeight, _ = vmutil.GetIssuanceProgramRestrictHeight(a.IssuanceProgram)
annotatedAsset.LimitHeight = vmutil.GetIssuanceProgramRestrictHeight(a.IssuanceProgram)
if a.Signer != nil {
annotatedAsset.AnnotatedSigner = query.AnnotatedSigner{
Type: a.Signer.Type,
......
package txbuilder
import (
"github.com/bytom/consensus"
"github.com/bytom/consensus/segwit"
"github.com/bytom/protocol/bc/types"
"github.com/bytom/protocol/vm/vmutil"
)
// EstimateTxGasInfo estimate transaction consumed gas
type EstimateTxGasInfo struct {
TotalNeu int64 `json:"total_neu"`
FlexibleNeu int64 `json:"flexible_neu"`
StorageNeu int64 `json:"storage_neu"`
VMNeu int64 `json:"vm_neu"`
}
// EstimateTxGas estimate consumed neu for transaction
func EstimateTxGas(template Template) (*EstimateTxGasInfo, error) {
var baseP2WSHSize, totalWitnessSize, baseP2WSHGas, totalP2WPKHGas, totalP2WSHGas, totalIssueGas int64
baseSize := int64(176) // inputSize(112) + outputSize(64)
baseP2WPKHSize := int64(98)
baseP2WPKHGas := int64(1409)
for pos, input := range template.Transaction.TxData.Inputs {
switch input.InputType() {
case types.SpendInputType:
controlProgram := input.ControlProgram()
if segwit.IsP2WPKHScript(controlProgram) {
totalWitnessSize += baseP2WPKHSize
totalP2WPKHGas += baseP2WPKHGas
} else if segwit.IsP2WSHScript(controlProgram) {
baseP2WSHSize, baseP2WSHGas = estimateP2WSHGas(template.SigningInstructions[pos])
totalWitnessSize += baseP2WSHSize
totalP2WSHGas += baseP2WSHGas
}
case types.IssuanceInputType:
issuanceProgram := input.IssuanceProgram()
if height := vmutil.GetIssuanceProgramRestrictHeight(issuanceProgram); height > 0 {
// the gas for issue program with checking block height
totalIssueGas += 5
}
baseIssueSize, baseIssueGas := estimateIssueGas(template.SigningInstructions[pos])
totalWitnessSize += baseIssueSize
totalIssueGas += baseIssueGas
}
}
flexibleGas := int64(0)
if totalP2WPKHGas > 0 {
flexibleGas += baseP2WPKHGas + (baseSize+baseP2WPKHSize)*consensus.StorageGasRate
} else if totalP2WSHGas > 0 {
flexibleGas += baseP2WSHGas + (baseSize+baseP2WSHSize)*consensus.StorageGasRate
} else if totalIssueGas > 0 {
totalIssueGas += baseP2WPKHGas
totalWitnessSize += baseSize + baseP2WPKHSize
}
// the total transaction storage gas
totalTxSizeGas := (int64(template.Transaction.TxData.SerializedSize) + totalWitnessSize) * consensus.StorageGasRate
// the total transaction gas is composed of storage and virtual machines
totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas + totalIssueGas + flexibleGas
return &EstimateTxGasInfo{
TotalNeu: totalGas * consensus.VMGasRate,
FlexibleNeu: flexibleGas * consensus.VMGasRate,
StorageNeu: totalTxSizeGas * consensus.VMGasRate,
VMNeu: (totalP2WPKHGas + totalP2WSHGas + totalIssueGas) * consensus.VMGasRate,
}, nil
}
// estimateP2WSH return the witness size and the gas consumed to execute the virtual machine for P2WSH program
func estimateP2WSHGas(sigInst *SigningInstruction) (int64, int64) {
var witnessSize, gas int64
for _, witness := range sigInst.WitnessComponents {
switch t := witness.(type) {
case *SignatureWitness:
witnessSize += 33*int64(len(t.Keys)) + 65*int64(t.Quorum)
gas += 1131*int64(len(t.Keys)) + 72*int64(t.Quorum) + 659
if int64(len(t.Keys)) == 1 && int64(t.Quorum) == 1 {
gas += 27
}
case *RawTxSigWitness:
witnessSize += 33*int64(len(t.Keys)) + 65*int64(t.Quorum)
gas += 1131*int64(len(t.Keys)) + 72*int64(t.Quorum) + 659
if int64(len(t.Keys)) == 1 && int64(t.Quorum) == 1 {
gas += 27
}
}
}
return witnessSize, gas
}
// estimateIssueGas return the witness size and the gas consumed to execute the virtual machine for issuance program
func estimateIssueGas(sigInst *SigningInstruction) (int64, int64) {
var witnessSize, gas int64
for _, witness := range sigInst.WitnessComponents {
switch t := witness.(type) {
case *SignatureWitness:
witnessSize += 65 * int64(t.Quorum)
gas += 1065*int64(len(t.Keys)) + 72*int64(t.Quorum) + 316
case *RawTxSigWitness:
witnessSize += 65 * int64(t.Quorum)
gas += 1065*int64(len(t.Keys)) + 72*int64(t.Quorum) + 316
}
}
return witnessSize, gas
}
This diff is collapsed.
......@@ -48,8 +48,8 @@ func FinalizeTx(ctx context.Context, c *protocol.Chain, tx *types.Tx) error {
if err != nil {
return err
}
tx.TxData.SerializedSize = uint64(len(data))
tx.Tx.SerializedSize = uint64(len(data))
tx.TxData.SerializedSize = uint64(len(data) / 2)
tx.Tx.SerializedSize = uint64(len(data) / 2)
isOrphan, err := c.ValidateTx(tx)
if errors.Root(err) == protocol.ErrBadTx {
......
......@@ -28,6 +28,7 @@ func init() {
runNodeCmd.Flags().Bool("wallet.disable", config.Wallet.Disable, "Disable wallet")
runNodeCmd.Flags().Bool("wallet.rescan", config.Wallet.Rescan, "Rescan wallet")
runNodeCmd.Flags().Bool("wallet.txindex", config.Wallet.TxIndex, "Save global tx index")
runNodeCmd.Flags().Bool("vault_mode", config.VaultMode, "Run in the offline enviroment")
runNodeCmd.Flags().Bool("web.closed", config.Web.Closed, "Lanch web browser or not")
runNodeCmd.Flags().String("chain_id", config.ChainID, "Select network type")
......@@ -40,6 +41,7 @@ func init() {
runNodeCmd.Flags().String("p2p.seeds", config.P2P.Seeds, "Comma delimited host:port seed nodes")
runNodeCmd.Flags().String("p2p.node_key", config.P2P.PrivateKey, "Node key for p2p communication")
runNodeCmd.Flags().Bool("p2p.skip_upnp", config.P2P.SkipUPNP, "Skip UPNP configuration")
runNodeCmd.Flags().Bool("p2p.lan_discoverable", config.P2P.LANDiscover, "Whether the node can be discovered by nodes in the LAN")
runNodeCmd.Flags().Int("p2p.max_num_peers", config.P2P.MaxNumPeers, "Set max num peers")
runNodeCmd.Flags().Int("p2p.handshake_timeout", config.P2P.HandshakeTimeout, "Set handshake timeout")
runNodeCmd.Flags().Int("p2p.dial_timeout", config.P2P.DialTimeout, "Set dial timeout")
......
......@@ -149,6 +149,7 @@ type P2PConfig struct {
PrivateKey string `mapstructure:"node_key"`
NodeKeyFile string `mapstructure:"node_key_file"`
SkipUPNP bool `mapstructure:"skip_upnp"`
LANDiscover bool `mapstructure:"lan_discoverable"`
MaxNumPeers int `mapstructure:"max_num_peers"`
HandshakeTimeout int `mapstructure:"handshake_timeout"`
DialTimeout int `mapstructure:"dial_timeout"`
......@@ -164,6 +165,7 @@ func DefaultP2PConfig() *P2PConfig {
ListenAddress: "tcp://0.0.0.0:46656",
NodeKeyFile: "nodekey",
SkipUPNP: false,
LANDiscover: true,
MaxNumPeers: 50,
HandshakeTimeout: 30,
DialTimeout: 3,
......@@ -177,6 +179,7 @@ func DefaultP2PConfig() *P2PConfig {
type WalletConfig struct {
Disable bool `mapstructure:"disable"`
Rescan bool `mapstructure:"rescan"`
TxIndex bool `mapstructure:"txindex"`
MaxTxFee uint64 `mapstructure:"max_tx_fee"`
}
......@@ -216,6 +219,7 @@ func DefaultWalletConfig() *WalletConfig {
return &WalletConfig{
Disable: false,
Rescan: false,
TxIndex: false,
MaxTxFee: uint64(1000000000),
}
}
......
......@@ -36,7 +36,7 @@ seeds = "45.79.213.28:46657,198.74.61.131:46657,212.111.41.245:46657,47.100.214.
var testNetConfigTmpl = `chain_id = "wisdom"
[p2p]
laddr = "tcp://0.0.0.0:46656"
seeds = "52.83.107.224:46656,52.83.107.224:46656,52.83.251.197:46656"
seeds = "52.83.107.224:46656,52.83.251.197:46656"
`
var soloNetConfigTmpl = `chain_id = "solonet"
......
......@@ -133,6 +133,8 @@ var MainNetParams = Params{
{157000, bc.NewHash([32]byte{0xb7, 0x70, 0x38, 0x4c, 0x81, 0x32, 0xaf, 0x12, 0x8d, 0xfa, 0xb4, 0xeb, 0x46, 0x4e, 0xb7, 0xeb, 0x66, 0x14, 0xd9, 0x24, 0xc2, 0xd1, 0x0c, 0x9c, 0x14, 0x20, 0xc9, 0xea, 0x0e, 0x85, 0xc8, 0xc3})},
{180000, bc.NewHash([32]byte{0x3c, 0x2a, 0x91, 0x55, 0xf3, 0x36, 0x6a, 0x5a, 0x60, 0xcf, 0x84, 0x42, 0xec, 0x4d, 0x0c, 0x63, 0xbc, 0x34, 0xe9, 0x1d, 0x1c, 0x6b, 0xb0, 0xf0, 0x50, 0xf3, 0xfb, 0x2d, 0xf6, 0xa1, 0xd9, 0x5c})},
{191000, bc.NewHash([32]byte{0x09, 0x4f, 0xe3, 0x23, 0x91, 0xb5, 0x11, 0x18, 0x68, 0xcc, 0x99, 0x9f, 0xeb, 0x95, 0xf9, 0xcc, 0xa5, 0x27, 0x6a, 0xf9, 0x0e, 0xda, 0x1b, 0xc6, 0x2e, 0x03, 0x29, 0xfe, 0x08, 0xdd, 0x2b, 0x01})},
{205000, bc.NewHash([32]byte{0x6f, 0xdd, 0x87, 0x26, 0x73, 0x3f, 0x0b, 0xc7, 0x58, 0x64, 0xa4, 0xdf, 0x45, 0xe4, 0x50, 0x27, 0x68, 0x38, 0x18, 0xb9, 0xa9, 0x44, 0x56, 0x20, 0x34, 0x68, 0xd8, 0x68, 0x72, 0xdb, 0x65, 0x6f})},
{219700, bc.NewHash([32]byte{0x98, 0x49, 0x8d, 0x4b, 0x7e, 0xe9, 0x44, 0x55, 0xc1, 0x07, 0xdd, 0x9a, 0xba, 0x6b, 0x49, 0x92, 0x61, 0x15, 0x03, 0x4f, 0x59, 0x42, 0x35, 0x74, 0xea, 0x3b, 0xdb, 0x2c, 0x53, 0x11, 0x75, 0x74})},
},
}
......
......@@ -26,6 +26,8 @@ const (
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
......@@ -41,6 +43,15 @@ func (priv PrivateKey) Public() PublicKey {
return PublicKey(publicKey)
}
// Seed returns the private key seed corresponding to priv. It is provided for
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
// in this package.
func (priv PrivateKey) Seed() []byte {
seed := make([]byte, SeedSize)
copy(seed, priv[:32])
return seed
}
func (priv PrivateKey) String() string {
return hex.EncodeToString(priv)
}
......@@ -77,6 +88,34 @@ func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, er
return publicKey, privateKey, nil
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
if l := len(seed); l != SeedSize {
panic("ed25519: bad seed length: " + strconv.Itoa(l))
}
digest := sha512.Sum512(seed)
digest[0] &= 248
digest[31] &= 127
digest[31] |= 64
var A edwards25519.ExtendedGroupElement
var hBytes [32]byte
copy(hBytes[:], digest[:])
edwards25519.GeScalarMultBase(&A, &hBytes)
var publicKeyBytes [32]byte
A.ToBytes(&publicKeyBytes)
privateKey := make([]byte, PrivateKeySize)
copy(privateKey, seed)
copy(privateKey[32:], publicKeyBytes[:])
return privateKey
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
......
This diff is collapsed.
Bytom version 1.0.9 is now available from:
https://github.com/Bytom/bytom/releases/tag/v1.0.9
Please report bugs using the issue tracker at github:
https://github.com/Bytom/bytom/issues
How to Upgrade
===============
If you are running an older version, shut it down. Wait until it has quited completely, and then run the new version Bytom.
You can operate according to the user manual.[(Bytom User Manual)](https://bytom.io/wp-content/themes/freddo/images/wallet/BytomUsermanualV1.0_en.pdf)
1.0.9 changelog
================
__Bytom Node__
+ `PR #1657`
- Save the index for all history transactions when "txindex" flag is provided for the purpose of future querying.
+ `PR #1659`
- Add dust transaction filter rule to filer the transaction with dust output amount.
+ `PR #1662`
- Add a keep_dial option in order to automatically retry connecting to provided peers.
+ `PR #1677`
- Add a custom node alias feature, support custom the node's name by the configuration.
+ `PR #1687`
- Support mDNS LAN peer discover to reduce the network bandwidth required for communication.
+ `PR #1692`
- Add ugly transaction test that may occur in several scenes such as insufficient fee, unbalanced transaction, overflow, and signature fail tests.
+ `PR #1697`
- Precisely estimate gas for standard transaction and issue transaction.
+ `PR #1698`
- Add timestamp as random number generator seed number, ensure random number security.
__Bytom Dashboard__
- Update the Json structure and add new form stepper for the create asset page.
- Add the issue asset option under the new transactions page. Support multi-signature under the issue asset transactions.
Credits
--------
Thanks to everyone who directly contributed to this release:
- Agouri
- Colt-Z
- HAOYUatHZ
- langyu
- Paladz
- shenao78
- shengling2008
- yahtoo
- zcc0721
- ZhitingLin
And everyone who helped test.
......@@ -24,7 +24,7 @@ var (
ErrDuplicateSubscribe = errors.New("event: subscribe duplicate type")
)
type NewMinedBlockEvent struct{ Block *types.Block }
type NewMinedBlockEvent struct{ Block types.Block }
// TypeMuxEvent is a time-tagged notification pushed to subscribers.
type TypeMuxEvent struct {
......
......@@ -102,7 +102,7 @@ out:
}).Info("Miner processed block")
// Broadcast the block and announce chain insertion event
if err = m.eventDispatcher.Post(event.NewMinedBlockEvent{Block: block}); err != nil {
if err = m.eventDispatcher.Post(event.NewMinedBlockEvent{Block: *block}); err != nil {
log.WithFields(log.Fields{"module": logModule, "height": block.BlockHeader.Height, "error": err}).Errorf("Miner fail on post block")
}
} else {
......
......@@ -121,7 +121,7 @@ func (m *MiningPool) submitWork(bh *types.BlockHeader) error {
return errors.New("submit result is orphan")
}
if err := m.eventDispatcher.Post(event.NewMinedBlockEvent{Block: m.block}); err != nil {
if err := m.eventDispatcher.Post(event.NewMinedBlockEvent{Block: *m.block}); err != nil {
return err
}
......
......@@ -480,7 +480,7 @@ func (sm *SyncManager) minedBroadcastLoop() {
continue
}
if err := sm.peers.broadcastMinedBlock(ev.Block); err != nil {
if err := sm.peers.broadcastMinedBlock(&ev.Block); err != nil {
log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on broadcast mine block")
continue
}
......
......@@ -30,6 +30,7 @@ type BasePeer interface {
ServiceFlag() consensus.ServiceFlag
TrafficStatus() (*flowrate.Status, *flowrate.Status)
TrySend(byte, interface{}) bool
IsLAN() bool
}
//BasePeerSet is the intergace for connection level peer manager
......@@ -367,7 +368,7 @@ func (ps *peerSet) bestPeer(flag consensus.ServiceFlag) *peer {
if !p.services.IsEnable(flag) {
continue
}
if bestPeer == nil || p.height > bestPeer.height {
if bestPeer == nil || p.height > bestPeer.height || (p.height == bestPeer.height && p.IsLAN()) {
bestPeer = p
}
}
......
......@@ -44,6 +44,10 @@ func (p *P2PPeer) ID() string {
return p.id
}
func (p *P2PPeer) IsLAN() bool {
return false
}
func (p *P2PPeer) ServiceFlag() consensus.ServiceFlag {
return p.flag
}
......
......@@ -2,6 +2,7 @@ package netsync
import (
"math/rand"
"time"
log "github.com/sirupsen/logrus"
......@@ -113,7 +114,7 @@ func (sm *SyncManager) txSyncLoop() {
return nil
}
n := rand.Intn(len(pending)) + 1
n := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(pending)) + 1
for _, s := range pending {
if n--; n == 0 {
return s
......
......@@ -22,6 +22,8 @@ import (
"github.com/bytom/blockchain/txfeed"
cfg "github.com/bytom/config"
"github.com/bytom/consensus"
"github.com/bytom/database"
dbm "github.com/bytom/database/leveldb"
"github.com/bytom/env"
"github.com/bytom/event"
"github.com/bytom/mining/cpuminer"
......@@ -32,8 +34,6 @@ import (
"github.com/bytom/p2p"
"github.com/bytom/protocol"
w "github.com/bytom/wallet"
dbm "github.com/bytom/database/leveldb"
"github.com/bytom/database"
)
const (
......@@ -109,7 +109,7 @@ func NewNode(config *cfg.Config) *Node {
walletDB := dbm.NewDB("wallet", config.DBBackend, config.DBDir())
accounts = account.NewManager(walletDB, chain)
assets = asset.NewRegistry(walletDB, chain)
wallet, err = w.NewWallet(walletDB, accounts, assets, hsm, chain, dispatcher)
wallet, err = w.NewWallet(walletDB, accounts, assets, hsm, chain, dispatcher, config.Wallet.TxIndex)
if err != nil {
log.WithFields(log.Fields{"module": logModule, "error": err}).Error("init NewWallet")