Example #1
0
// NewWhisperFilter creates and registers a new message filter to watch for inbound whisper messages.
func (s *PublicWhisperAPI) NewFilter(args *NewFilterArgs) (*rpc.HexNumber, error) {
	if s.w == nil {
		return nil, whisperOffLineErr
	}

	var id int
	filter := Filter{
		To:     crypto.ToECDSAPub(common.FromHex(args.To)),
		From:   crypto.ToECDSAPub(common.FromHex(args.From)),
		Topics: NewFilterTopics(args.Topics...),
		Fn: func(message *Message) {
			wmsg := NewWhisperMessage(message)
			s.messagesMu.RLock() // Only read lock to the filter pool
			defer s.messagesMu.RUnlock()
			if s.messages[id] != nil {
				s.messages[id].insert(wmsg)
			}
		},
	}

	id = s.w.Watch(filter)

	s.messagesMu.Lock()
	s.messages[id] = newWhisperFilter(id, s.w)
	s.messagesMu.Unlock()

	return rpc.NewHexNumber(id), nil
}
Example #2
0
// Post injects a message into the whisper network for distribution.
func (s *PublicWhisperAPI) Post(args *PostArgs) (bool, error) {
	if s.w == nil {
		return false, whisperOffLineErr
	}

	// construct whisper message with transmission options
	message := NewMessage(common.FromHex(args.Payload))
	options := Options{
		To:     crypto.ToECDSAPub(common.FromHex(args.To)),
		TTL:    time.Duration(args.TTL) * time.Second,
		Topics: NewTopics(args.Topics...),
	}

	// set sender identity
	if len(args.From) > 0 {
		if key := s.w.GetIdentity(crypto.ToECDSAPub(common.FromHex(args.From))); key != nil {
			options.From = key
		} else {
			return false, fmt.Errorf("unknown identity to send from: %s", args.From)
		}
	}

	// Wrap and send the message
	pow := time.Duration(args.Priority) * time.Millisecond
	envelope, err := message.Wrap(pow, options)
	if err != nil {
		return false, err
	}

	return true, s.w.Send(envelope)
}
Example #3
0
func (args *PostArgs) UnmarshalJSON(data []byte) (err error) {
	var obj struct {
		From     string        `json:"from"`
		To       string        `json:"to"`
		Topics   []string      `json:"topics"`
		Payload  string        `json:"payload"`
		Priority rpc.HexNumber `json:"priority"`
		TTL      rpc.HexNumber `json:"ttl"`
	}

	if err := json.Unmarshal(data, &obj); err != nil {
		return err
	}

	args.From = obj.From
	args.To = obj.To
	args.Payload = obj.Payload
	args.Priority = obj.Priority.Int64()
	args.TTL = obj.TTL.Int64()

	// decode topic strings
	args.Topics = make([][]byte, len(obj.Topics))
	for i, topic := range obj.Topics {
		args.Topics[i] = common.FromHex(topic)
	}

	return nil
}
Example #4
0
// BlockNumber retrieves the current head number of the blockchain.
func (api *API) BlockNumber() (uint64, error) {
	res, err := api.request("eth_blockNumber", nil)
	if err != nil {
		return 0, err
	}
	var hex string
	if err := json.Unmarshal(res, &hex); err != nil {
		return 0, err
	}
	return new(big.Int).SetBytes(common.FromHex(hex)).Uint64(), nil
}
Example #5
0
// Syncing returns the current sync status of the node, or nil if the node is not
// currently synchronizing with the network.
func (api *API) Syncing() (*SyncStatus, error) {
	// Execute the request and check if syncing is not running
	res, err := api.request("eth_syncing", nil)
	if err != nil {
		return nil, err
	}
	var running bool
	if err := json.Unmarshal(res, &running); err == nil {
		return nil, nil
	}
	// Sync is running, extract the current status
	result := make(map[string]string)
	if err := json.Unmarshal(res, &result); err != nil {
		return nil, err
	}
	return &SyncStatus{
		StartingBlock: new(big.Int).SetBytes(common.FromHex(result["startingBlock"])).Uint64(),
		CurrentBlock:  new(big.Int).SetBytes(common.FromHex(result["currentBlock"])).Uint64(),
		HighestBlock:  new(big.Int).SetBytes(common.FromHex(result["highestBlock"])).Uint64(),
	}, nil
}
Example #6
0
func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) {
	if block := blockByNumber(s.miner, s.bc, blockNr); block != nil {
		stateDb, err := state.New(block.Root(), s.chainDb)
		if err != nil {
			return "0x", nil, err
		}

		stateDb = stateDb.Copy()
		var from *state.StateObject
		if args.From == (common.Address{}) {
			accounts, err := s.am.Accounts()
			if err != nil || len(accounts) == 0 {
				from = stateDb.GetOrNewStateObject(common.Address{})
			} else {
				from = stateDb.GetOrNewStateObject(accounts[0].Address)
			}
		} else {
			from = stateDb.GetOrNewStateObject(args.From)
		}

		from.SetBalance(common.MaxBig)

		msg := callmsg{
			from:     from,
			to:       &args.To,
			gas:      args.Gas.BigInt(),
			gasPrice: args.GasPrice.BigInt(),
			value:    args.Value.BigInt(),
			data:     common.FromHex(args.Data),
		}

		if msg.gas.Cmp(common.Big0) == 0 {
			msg.gas = big.NewInt(50000000)
		}

		if msg.gasPrice.Cmp(common.Big0) == 0 {
			msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
		}

		header := s.bc.CurrentBlock().Header()
		vmenv := core.NewEnv(stateDb, s.bc, msg, header)
		gp := new(core.GasPool).AddGas(common.MaxBig)
		res, gas, err := core.ApplyMessage(vmenv, msg, gp)
		if len(res) == 0 { // backwards compatability
			return "0x", gas, err
		}
		return common.ToHex(res), gas, err
	}

	return "0x", common.Big0, nil
}
Example #7
0
// GetBlockTime retrieves the block of the given number from the canonical chain.
func (api *API) GetBlockTime(num uint64) (time.Time, error) {
	res, err := api.request("eth_getBlockByNumber", []interface{}{rpc.NewHexNumber(num), true})
	if err != nil {
		return time.Time{}, err
	}
	result := make(map[string]json.RawMessage)
	if err := json.Unmarshal(res, &result); err != nil {
		return time.Time{}, err
	}
	var hex string
	if err := json.Unmarshal(result["timestamp"], &hex); err != nil {
		return time.Time{}, err
	}
	return time.Unix(new(big.Int).SetBytes(common.FromHex(hex)).Int64(), 0), nil
}
Example #8
0
// Call forms a transaction from the given arguments and tries to execute it on
// a private VM with a copy of the state. Any changes are therefore only temporary
// and not part of the actual state. This allows for local execution/queries.
func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) {
	block := be.bc.CurrentBlock()
	statedb, err := state.New(block.Root(), be.chainDb)
	if err != nil {
		return "", "", err
	}

	var from *state.StateObject
	if len(fromStr) == 0 {
		accounts, err := be.am.Accounts()
		if err != nil || len(accounts) == 0 {
			from = statedb.GetOrNewStateObject(common.Address{})
		} else {
			from = statedb.GetOrNewStateObject(accounts[0].Address)
		}
	} else {
		from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr))
	}

	from.SetBalance(common.MaxBig)

	msg := callmsg{
		from:     from,
		gas:      common.Big(gasStr),
		gasPrice: common.Big(gasPriceStr),
		value:    common.Big(valueStr),
		data:     common.FromHex(dataStr),
	}
	if len(toStr) > 0 {
		addr := common.HexToAddress(toStr)
		msg.to = &addr
	}

	if msg.gas.Cmp(big.NewInt(0)) == 0 {
		msg.gas = big.NewInt(50000000)
	}

	if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
		msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
	}

	header := be.bc.CurrentBlock().Header()
	vmenv := core.NewEnv(statedb, be.bc, msg, header)
	gp := new(core.GasPool).AddGas(common.MaxBig)
	res, gas, err := core.ApplyMessage(vmenv, msg, gp)

	return common.ToHex(res), gas.String(), err
}
Example #9
0
// SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(encodedTx string) (string, error) {
	tx := new(types.Transaction)
	if err := rlp.DecodeBytes(common.FromHex(encodedTx), tx); err != nil {
		return "", err
	}

	s.txPool.SetLocal(tx)
	if err := s.txPool.Add(tx); err != nil {
		return "", err
	}

	if tx.To() == nil {
		from, err := tx.From()
		if err != nil {
			return "", err
		}
		addr := crypto.CreateAddress(from, tx.Nonce())
		glog.V(logger.Info).Infof("Tx(%x) created: %x\n", tx.Hash(), addr)
	} else {
		glog.V(logger.Info).Infof("Tx(%x) to: %x\n", tx.Hash(), tx.To())
	}

	return tx.Hash().Hex(), nil
}
Example #10
0
// HasIdentity checks if the the whisper node is configured with the private key
// of the specified public pair.
func (s *PublicWhisperAPI) HasIdentity(identity string) (bool, error) {
	if s.w == nil {
		return false, whisperOffLineErr
	}
	return s.w.HasIdentity(crypto.ToECDSAPub(common.FromHex(identity))), nil
}
Example #11
0
// UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a
// JSON message blob into a WhisperFilterArgs structure.
func (args *NewFilterArgs) UnmarshalJSON(b []byte) (err error) {
	// Unmarshal the JSON message and sanity check
	var obj struct {
		To     interface{} `json:"to"`
		From   interface{} `json:"from"`
		Topics interface{} `json:"topics"`
	}
	if err := json.Unmarshal(b, &obj); err != nil {
		return err
	}

	// Retrieve the simple data contents of the filter arguments
	if obj.To == nil {
		args.To = ""
	} else {
		argstr, ok := obj.To.(string)
		if !ok {
			return fmt.Errorf("to is not a string")
		}
		args.To = argstr
	}
	if obj.From == nil {
		args.From = ""
	} else {
		argstr, ok := obj.From.(string)
		if !ok {
			return fmt.Errorf("from is not a string")
		}
		args.From = argstr
	}
	// Construct the nested topic array
	if obj.Topics != nil {
		// Make sure we have an actual topic array
		list, ok := obj.Topics.([]interface{})
		if !ok {
			return fmt.Errorf("topics is not an array")
		}
		// Iterate over each topic and handle nil, string or array
		topics := make([][]string, len(list))
		for idx, field := range list {
			switch value := field.(type) {
			case nil:
				topics[idx] = []string{}

			case string:
				topics[idx] = []string{value}

			case []interface{}:
				topics[idx] = make([]string, len(value))
				for i, nested := range value {
					switch value := nested.(type) {
					case nil:
						topics[idx][i] = ""

					case string:
						topics[idx][i] = value

					default:
						return fmt.Errorf("topic[%d][%d] is not a string", idx, i)
					}
				}
			default:
				return fmt.Errorf("topic[%d] not a string or array", idx)
			}
		}

		topicsDecoded := make([][][]byte, len(topics))
		for i, condition := range topics {
			topicsDecoded[i] = make([][]byte, len(condition))
			for j, topic := range condition {
				topicsDecoded[i][j] = common.FromHex(topic)
			}
		}

		args.Topics = topicsDecoded
	}
	return nil
}
Example #12
0
// ServeHTTP implements http.Handler, extracting and validating payment headers
// contained within the HTTP request. If payment information is accepted, the
// request is passed on to the internal service for execution. Otherwise the proxy
// short circuits the request and sends back an appropriate error.
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	reqLogger := p.logger.New("request-id", atomic.AddUint32(&p.autoid, 1))
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Expose-Headers", VerificationHeader)

	// Short circuit CORS pre-flight requests
	if r.Method == "OPTIONS" {
		reqLogger.Debug("Allowing CORS pre-flight request")
		w.Header().Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers"))
		return
	}
	// Allow head requests through for data APIs to query the content size
	if r.Method == "HEAD" {
		reqLogger.Debug("Allowing data HEAD request")
		w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Range")

		res, err := p.service(r)
		if err != nil {
			reqLogger.Error("Failed to process API request", "error", err)
			http.Error(w, "Failed to execute request", http.StatusInternalServerError)
			return
		}
		defer res.Body.Close()

		p.forward(w, res)
		return
	}
	// Retrieve the authorization header from the original request
	authHeader := r.Header.Get(AuthorizationHeader)
	reqLogger.Debug("Received an API request", "authorization", authHeader)

	// Ensure that all payment information are present
	if authHeader == "" {
		p.fail(w, &verification{Error: "Missing HTTP header: " + AuthorizationHeader})
		return
	}
	auth := new(authorization)
	if err := json.Unmarshal([]byte(authHeader), auth); err != nil {
		p.fail(w, &verification{Error: "Invalid authorization header: " + err.Error()})
		return
	}
	// Process the request and payment based on the proxy type
	switch p.kind {
	case CallProxy:
		// Make sure the consumer authorized the payment for this call
		consumer, provider := common.HexToAddress(auth.Consumer), common.HexToAddress(auth.Provider)

		if !p.verifier.Exists(consumer, provider) {
			p.fail(w, &verification{Unknown: true, Error: "Non existent API subscription"})
			return
		}

		nonce := p.verifier.Nonce(consumer, provider).Uint64()
		if auth.Nonce != nonce {
			p.fail(w, &verification{Error: "Invalid nonce", Nonce: nonce})
			return
		}

		valid, funded := p.verifier.Verify(consumer, provider, auth.Nonce, new(big.Int).SetUint64(auth.Amount), common.FromHex(auth.Signature))
		if !valid {
			p.fail(w, &verification{Error: "Invalid authorization signature"})
			return
		}
		if !funded {
			p.fail(w, &verification{Error: "Not enough funds available"})
			return
		}

		price := p.verifier.Price(consumer, provider).Uint64()
		if prev := p.vault.Fetch(provider, consumer); prev != nil && prev.Amount+price > auth.Amount {
			p.fail(w, &verification{
				Error:      "Not enough funds authorized",
				Authorized: prev.Amount,
				Proof:      prev.Signature,
				Need:       prev.Amount + price,
			})
			return
		}
		p.vault.Store(auth)

		// Execute the API internally and proxy the response
		reqLogger.Debug("Payment accepted for API invocation")
		res, err := p.service(r)
		if err != nil {
			reqLogger.Error("Failed to process API request", "error", err)
			http.Error(w, "Failed to execute request", http.StatusInternalServerError)
			return
		}
		defer res.Body.Close()
		p.forward(w, res)

	case DataProxy:
		// Since we're paying by the data, retrieve the amount first
		res, err := p.service(r)
		if err != nil {
			reqLogger.Error("Failed to process API request", "error", err)
			http.Error(w, "Failed to execute request", http.StatusInternalServerError)
			return
		}
		defer res.Body.Close()

		// Make sure the user authorized payment for all the requested data
		data := res.ContentLength
		if data > 0 /* TODO */ {
			reqLogger.Debug("Payment accepted for API stream", "data", data)
			p.forward(w, res)
		}
	}
}
Example #13
0
// WriteGenesisBlock writes the genesis block to the database as block number 0
func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, error) {
	contents, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, err
	}

	var genesis struct {
		Nonce      string
		Timestamp  string
		ParentHash string
		ExtraData  string
		GasLimit   string
		Difficulty string
		Mixhash    string
		Coinbase   string
		Alloc      map[string]struct {
			Code    string
			Storage map[string]string
			Balance string
		}
	}

	if err := json.Unmarshal(contents, &genesis); err != nil {
		return nil, err
	}

	// creating with empty hash always works
	statedb, _ := state.New(common.Hash{}, chainDb)
	for addr, account := range genesis.Alloc {
		address := common.HexToAddress(addr)
		statedb.AddBalance(address, common.String2Big(account.Balance))
		statedb.SetCode(address, common.Hex2Bytes(account.Code))
		for key, value := range account.Storage {
			statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
		}
	}
	root, stateBatch := statedb.CommitBatch()

	difficulty := common.String2Big(genesis.Difficulty)
	block := types.NewBlock(&types.Header{
		Nonce:      types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()),
		Time:       common.String2Big(genesis.Timestamp),
		ParentHash: common.HexToHash(genesis.ParentHash),
		Extra:      common.FromHex(genesis.ExtraData),
		GasLimit:   common.String2Big(genesis.GasLimit),
		Difficulty: difficulty,
		MixDigest:  common.HexToHash(genesis.Mixhash),
		Coinbase:   common.HexToAddress(genesis.Coinbase),
		Root:       root,
	}, nil, nil, nil)

	if block := GetBlock(chainDb, block.Hash()); block != nil {
		glog.V(logger.Info).Infoln("Genesis block already in chain. Writing canonical number")
		err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
		if err != nil {
			return nil, err
		}
		return block, nil
	}

	if err := stateBatch.Write(); err != nil {
		return nil, fmt.Errorf("cannot write state: %v", err)
	}
	if err := WriteTd(chainDb, block.Hash(), difficulty); err != nil {
		return nil, err
	}
	if err := WriteBlock(chainDb, block); err != nil {
		return nil, err
	}
	if err := WriteBlockReceipts(chainDb, block.Hash(), nil); err != nil {
		return nil, err
	}
	if err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()); err != nil {
		return nil, err
	}
	if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil {
		return nil, err
	}
	return block, nil
}
Example #14
0
// Transact forms a transaction from the given arguments and submits it to the
// transactio pool for execution.
func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
	if len(toStr) > 0 && toStr != "0x" && !common.IsHexAddress(toStr) {
		return "", errors.New("invalid address")
	}

	var (
		from             = common.HexToAddress(fromStr)
		to               = common.HexToAddress(toStr)
		value            = common.Big(valueStr)
		gas              *big.Int
		price            *big.Int
		data             []byte
		contractCreation bool
	)

	if len(gasStr) == 0 {
		gas = big.NewInt(90000)
	} else {
		gas = common.Big(gasStr)
	}

	if len(gasPriceStr) == 0 {
		price = big.NewInt(10000000000000)
	} else {
		price = common.Big(gasPriceStr)
	}

	data = common.FromHex(codeStr)
	if len(toStr) == 0 {
		contractCreation = true
	}

	nonce := be.txPool.State().GetNonce(from)
	if len(nonceStr) != 0 {
		nonce = common.Big(nonceStr).Uint64()
	}

	var tx *types.Transaction
	if contractCreation {
		tx = types.NewContractCreation(nonce, value, gas, price, data)
	} else {
		tx = types.NewTransaction(nonce, to, value, gas, price, data)
	}

	acc := accounts.Account{from}
	signature, err := be.am.Sign(acc, tx.SigHash().Bytes())
	if err != nil {
		return "", err
	}
	signedTx, err := tx.WithSignature(signature)
	if err != nil {
		return "", err
	}

	be.txPool.SetLocal(signedTx)
	if err := be.txPool.Add(signedTx); err != nil {
		return "", nil
	}

	if contractCreation {
		addr := crypto.CreateAddress(from, nonce)
		glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
	} else {
		glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
	}

	return signedTx.Hash().Hex(), nil
}
Example #15
0
// Charge will redeem all pending payments made to this provider since startup.
func (v *accountVault) Charge(charger Charger) {
	v.lock.RLock()
	for _, auth := range v.pends {
		tx, err := charger.Charge(common.HexToAddress(auth.Consumer), common.HexToAddress(auth.Provider), auth.Nonce, new(big.Int).SetUint64(auth.Amount), common.FromHex(auth.Signature))
		if err != nil {
			log15.Error("Failed to charge payment", "authorization", auth, "error", err)
		} else {
			log15.Info("Payment charged", "tx", "http://testnet.etherscan.io/tx/"+tx.Hex())
		}
	}
	v.lock.RUnlock()

	v.lock.Lock()
	for consumer, auth := range v.auths {
		if v.pends[consumer] == auth {
			delete(v.pends, consumer)
		}
	}
	v.lock.Unlock()
}
Example #16
0
// SendTransaction will create a transaction for the given transaction argument, sign it and submit it to the
// transaction pool.
func (s *PublicTransactionPoolAPI) SendTransaction(args SendTxArgs) (common.Hash, error) {
	if args.Gas == nil {
		args.Gas = rpc.NewHexNumber(defaultGas)
	}
	if args.GasPrice == nil {
		args.GasPrice = rpc.NewHexNumber(defaultGasPrice)
	}
	if args.Value == nil {
		args.Value = rpc.NewHexNumber(0)
	}

	s.txMu.Lock()
	defer s.txMu.Unlock()

	if args.Nonce == nil {
		args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From))
	}

	var tx *types.Transaction
	contractCreation := (args.To == common.Address{})

	if contractCreation {
		tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
	} else {
		tx = types.NewTransaction(args.Nonce.Uint64(), args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
	}

	signedTx, err := s.sign(args.From, tx)
	if err != nil {
		return common.Hash{}, err
	}

	s.txPool.SetLocal(signedTx)
	if err := s.txPool.Add(signedTx); err != nil {
		return common.Hash{}, nil
	}

	if contractCreation {
		addr := crypto.CreateAddress(args.From, args.Nonce.Uint64())
		glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
	} else {
		glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
	}

	return signedTx.Hash(), nil
}
Example #17
0
// Sha3 applies the ethereum sha3 implementation on the input.
// It assumes the input is hex encoded.
func (s *PublicWeb3API) Sha3(input string) string {
	return common.ToHex(crypto.Sha3(common.FromHex(input)))
}
Example #18
0
// SignTransaction will sign the given transaction with the from account.
// The node needs to have the private key of the account corresponding with
// the given from address and it needs to be unlocked.
func (s *PublicTransactionPoolAPI) SignTransaction(args *SignTransactionArgs) (*SignTransactionResult, error) {
	if args.Gas == nil {
		args.Gas = rpc.NewHexNumber(defaultGas)
	}
	if args.GasPrice == nil {
		args.GasPrice = rpc.NewHexNumber(defaultGasPrice)
	}
	if args.Value == nil {
		args.Value = rpc.NewHexNumber(0)
	}

	s.txMu.Lock()
	defer s.txMu.Unlock()

	if args.Nonce == nil {
		args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From))
	}

	var tx *types.Transaction
	contractCreation := (args.To == common.Address{})

	if contractCreation {
		tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
	} else {
		tx = types.NewTransaction(args.Nonce.Uint64(), args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
	}

	signedTx, err := s.sign(args.From, tx)
	if err != nil {
		return nil, err
	}

	data, err := rlp.EncodeToBytes(signedTx)
	if err != nil {
		return nil, err
	}

	return &SignTransactionResult{"0x" + common.Bytes2Hex(data), newTx(tx)}, nil
}