func (tx *Tx) UnmarshalJSON(b []byte) (err error) { req := struct { To common.Address `json:"to"` From common.Address `json:"from"` Nonce *rpc.HexNumber `json:"nonce"` Value *rpc.HexNumber `json:"value"` Data string `json:"data"` GasLimit *rpc.HexNumber `json:"gas"` GasPrice *rpc.HexNumber `json:"gasPrice"` Hash common.Hash `json:"hash"` }{} if err := json.Unmarshal(b, &req); err != nil { return err } contractCreation := (req.To == (common.Address{})) tx.To = &req.To tx.From = req.From tx.Nonce = req.Nonce tx.Value = req.Value tx.Data = req.Data tx.GasLimit = req.GasLimit tx.GasPrice = req.GasPrice tx.Hash = req.Hash data := common.Hex2Bytes(tx.Data) if tx.Nonce == nil { return fmt.Errorf("need nonce") } if tx.Value == nil { tx.Value = rpc.NewHexNumber(0) } if tx.GasLimit == nil { tx.GasLimit = rpc.NewHexNumber(0) } if tx.GasPrice == nil { tx.GasPrice = rpc.NewHexNumber(defaultGasPrice) } if contractCreation { tx.tx = types.NewContractCreation(tx.Nonce.Uint64(), tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data) } else { if tx.To == nil { return fmt.Errorf("need to address") } tx.tx = types.NewTransaction(tx.Nonce.Uint64(), *tx.To, tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data) } return nil }
// 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 }
// 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 }
// Resend accepts an existing transaction and a new gas price and limit. It will remove the given transaction from the // pool and reinsert it with the new gas price and limit. func (s *PublicTransactionPoolAPI) Resend(tx *Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) { pending := s.txPool.GetTransactions() for _, p := range pending { if pFrom, err := p.From(); err == nil && pFrom == tx.From && p.SigHash() == tx.tx.SigHash() { if gasPrice == nil { gasPrice = rpc.NewHexNumber(tx.tx.GasPrice()) } if gasLimit == nil { gasLimit = rpc.NewHexNumber(tx.tx.Gas()) } var newTx *types.Transaction contractCreation := (*tx.tx.To() == common.Address{}) if contractCreation { newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data()) } else { newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data()) } signedTx, err := s.sign(tx.From, newTx) if err != nil { return common.Hash{}, err } s.txPool.RemoveTx(tx.Hash) if err = s.txPool.Add(signedTx); err != nil { return common.Hash{}, err } return signedTx.Hash(), nil } } return common.Hash{}, fmt.Errorf("Transaction %#x not found", tx.Hash) }
// 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 }