Example #1
0
func (self *XEth) SignTransaction(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (*types.Transaction, error) {
	if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) {
		return nil, 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 = DefaultGas()
	} else {
		gas = common.Big(gasStr)
	}

	if len(gasPriceStr) == 0 {
		price = self.DefaultGasPrice()
	} else {
		price = common.Big(gasPriceStr)
	}

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

	var nonce uint64
	if len(nonceStr) != 0 {
		nonce = common.Big(nonceStr).Uint64()
	} else {
		state := self.backend.TxPool().State()
		nonce = state.GetNonce(from)
	}
	var tx *types.Transaction
	if contractCreation {
		tx = types.NewContractCreation(nonce, value, gas, price, data)
	} else {
		tx = types.NewTransaction(nonce, to, value, gas, price, data)
	}

	signed, err := self.sign(tx, from, false)
	if err != nil {
		return nil, err
	}

	return signed, nil
}
Example #2
0
// transact executes an actual transaction invocation, first deriving any missing
// authorization fields, and then scheduling the transaction for execution.
func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
	var err error

	// Ensure a valid value field and resolve the account nonce
	value := opts.Value
	if value == nil {
		value = new(big.Int)
	}
	nonce := uint64(0)
	if opts.Nonce == nil {
		nonce, err = c.transactor.PendingAccountNonce(opts.From)
		if err != nil {
			return nil, fmt.Errorf("failed to retrieve account nonce: %v", err)
		}
	} else {
		nonce = opts.Nonce.Uint64()
	}
	// Figure out the gas allowance and gas price values
	gasPrice := opts.GasPrice
	if gasPrice == nil {
		gasPrice, err = c.transactor.SuggestGasPrice()
		if err != nil {
			return nil, fmt.Errorf("failed to suggest gas price: %v", err)
		}
	}
	gasLimit := opts.GasLimit
	if gasLimit == nil {
		// Gas estimation cannot succeed without code for method invocations
		if contract != nil && atomic.LoadUint32(&c.pendingHasCode) == 0 {
			if code, err := c.transactor.HasCode(c.address, true); err != nil {
				return nil, err
			} else if !code {
				return nil, ErrNoCode
			}
			atomic.StoreUint32(&c.pendingHasCode, 1)
		}
		// If the contract surely has code (or code is not needed), estimate the transaction
		gasLimit, err = c.transactor.EstimateGasLimit(opts.From, contract, value, input)
		if err != nil {
			return nil, fmt.Errorf("failed to exstimate gas needed: %v", err)
		}
	}
	// Create the transaction, sign it and schedule it for execution
	var rawTx *types.Transaction
	if contract == nil {
		rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input)
	} else {
		rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input)
	}
	if opts.Signer == nil {
		return nil, errors.New("no signer to authorize the transaction with")
	}
	signedTx, err := opts.Signer(opts.From, rawTx)
	if err != nil {
		return nil, err
	}
	if err := c.transactor.SendTransaction(signedTx); err != nil {
		return nil, err
	}
	return signedTx, nil
}
Example #3
0
func (tx *tx) UnmarshalJSON(b []byte) (err error) {
	var fields map[string]interface{}
	if err := json.Unmarshal(b, &fields); err != nil {
		return shared.NewDecodeParamError(err.Error())
	}

	var (
		nonce            uint64
		to               common.Address
		amount           = new(big.Int).Set(common.Big0)
		gasLimit         = new(big.Int).Set(common.Big0)
		gasPrice         = new(big.Int).Set(common.Big0)
		data             []byte
		contractCreation = true
	)

	if val, found := fields["Hash"]; found {
		if hashVal, ok := val.(string); ok {
			tx.Hash = hashVal
		}
	}

	if val, found := fields["To"]; found {
		if strVal, ok := val.(string); ok && len(strVal) > 0 {
			tx.To = strVal
			to = common.HexToAddress(strVal)
			contractCreation = false
		}
	}

	if val, found := fields["From"]; found {
		if strVal, ok := val.(string); ok {
			tx.From = strVal
		}
	}

	if val, found := fields["Nonce"]; found {
		if strVal, ok := val.(string); ok {
			tx.Nonce = strVal
			if nonce, err = strconv.ParseUint(strVal, 10, 64); err != nil {
				return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.Nonce - %v", err))
			}
		}
	} else {
		return shared.NewDecodeParamError("tx.Nonce not found")
	}

	var parseOk bool
	if val, found := fields["Value"]; found {
		if strVal, ok := val.(string); ok {
			tx.Value = strVal
			if _, parseOk = amount.SetString(strVal, 0); !parseOk {
				return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.Amount - %v", err))
			}
		}
	}

	if val, found := fields["Data"]; found {
		if strVal, ok := val.(string); ok {
			tx.Data = strVal
			if strings.HasPrefix(strVal, "0x") {
				data = common.Hex2Bytes(strVal[2:])
			} else {
				data = common.Hex2Bytes(strVal)
			}
		}
	}

	if val, found := fields["GasLimit"]; found {
		if strVal, ok := val.(string); ok {
			tx.GasLimit = strVal
			if _, parseOk = gasLimit.SetString(strVal, 0); !parseOk {
				return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.GasLimit - %v", err))
			}
		}
	}

	if val, found := fields["GasPrice"]; found {
		if strVal, ok := val.(string); ok {
			tx.GasPrice = strVal
			if _, parseOk = gasPrice.SetString(strVal, 0); !parseOk {
				return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.GasPrice - %v", err))
			}
		}
	}

	if contractCreation {
		tx.tx = types.NewContractCreation(nonce, amount, gasLimit, gasPrice, data)
	} else {
		tx.tx = types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
	}

	return nil
}
Example #4
0
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {

	// this minimalistic recoding is enough (works for natspec.js)
	var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, toStr, codeStr)
	if !self.ConfirmTransaction(jsontx) {
		err := fmt.Errorf("Transaction not confirmed")
		return "", err
	}

	if len(toStr) > 0 && toStr != "0x" && !isAddress(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 = DefaultGas()
	} else {
		gas = common.Big(gasStr)
	}

	if len(gasPriceStr) == 0 {
		price = self.DefaultGasPrice()
	} else {
		price = common.Big(gasPriceStr)
	}

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

	// 2015-05-18 Is this still needed?
	// TODO if no_private_key then
	//if _, exists := p.register[args.From]; exists {
	//	p.register[args.From] = append(p.register[args.From], args)
	//} else {
	/*
		account := accounts.Get(common.FromHex(args.From))
		if account != nil {
			if account.Unlocked() {
				if !unlockAccount(account) {
					return
				}
			}

			result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data))
			if len(result) > 0 {
				*reply = common.ToHex(result)
			}
		} else if _, exists := p.register[args.From]; exists {
			p.register[ags.From] = append(p.register[args.From], args)
		}
	*/

	self.transactMu.Lock()
	defer self.transactMu.Unlock()

	var nonce uint64
	if len(nonceStr) != 0 {
		nonce = common.Big(nonceStr).Uint64()
	} else {
		state := self.backend.TxPool().State()
		nonce = state.GetNonce(from)
	}
	var tx *types.Transaction
	if contractCreation {
		tx = types.NewContractCreation(nonce, value, gas, price, data)
	} else {
		tx = types.NewTransaction(nonce, to, value, gas, price, data)
	}

	signed, err := self.sign(tx, from, false)
	if err != nil {
		return "", err
	}
	if err = self.backend.TxPool().Add(signed); err != nil {
		return "", err
	}

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

	return signed.Hash().Hex(), nil
}