Я хочу создать необработанную транзакцию, подписать ее и передать ее с помощью eth.sendRawTransaction
метода RPC.
Я хотел бы сделать это в автономном режиме, используя код или библиотеку с открытым исходным кодом ИЛИ онлайн, но без необходимости использования определенного кошелька или программного обеспечения.
Не существует ни метода RPC для создания/подписания необработанной транзакции, ни каких-либо библиотек для этого (в автономном режиме).
Любая помощь или руководство о том, как это может быть достигнуто, будут очень благодарны. Если есть реализация Python, это было бы здорово.
ethereumjs-tx — это библиотека с таким примером:
npm install ethereumjs-tx
const Tx = require('ethereumjs-tx').Transaction
var privateKey = new Buffer('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex')
var rawTx = {
nonce: '0x00',
gasPrice: '0x09184e72a000',
gasLimit: '0x2710',
to: '0x0000000000000000000000000000000000000000',
value: '0x00',
data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057'
}
var tx = new Tx(rawTx)
tx.sign(privateKey)
var serializedTx = tx.serialize()
console.log(serializedTx.toString('hex'))
sendRawTransaction
const Tx = require('ethereumjs-tx').Transaction
В Go создание подписанной транзакции будет выглядеть примерно так:
transaction := types.NewTransaction(nonce, recipient, value, gasLimit, gasPrice, input)
signature, _ := crypto.Sign(transaction.SigHash().Bytes(), key)
signed, _ := tx.WithSignature(signature)
где ключ является равниной *ecdsa.PrivateKey
. Если вы хотите использовать зашифрованные учетные записи Ethereum, вы можете взглянуть на AccountManager, который сделает за вас все причудливые криптографические вещи, и вы можете просто вызвать Sign
метод с входной транзакцией, чтобы подписать ее.
После того, как он будет подписан, вам все равно нужно объявить об этом через RPC в сети. Это уже реализовано для привязок Native DApp здесь: https://github.com/ethereum/go-ethereum/blob/develop/accounts/abi/bind/backends/remote.go#L202 , которые вы можете скопировать и вставить или, альтернативно, подождать немного, пока Феликс не закончит свой клиент RPC Go.
crypto
библиотеке вы здесь говорите? А можно ссылку на ваш types
файл?Вы можете использовать Web3 .
var Accounts = require('web3-eth-accounts');
// Passing in the eth or web3 package is necessary to allow retrieving chainId, gasPrice and nonce automatically
// for accounts.signTransaction().
// var accounts = new Accounts('ws://localhost:8546');
var accounts = new Accounts();
// if nonce, chainId, gas and gasPrice is given it returns synchronous
accounts.signTransaction({
to: '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55',
value: '1000000000',
gas: 2000000,
gasPrice: '234567897654321',
nonce: 0,
chainId: 1
}, '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318')
Выход:
{
messageHash: '0x6893a6ee8df79b0f5d64a180cd1ef35d030f3e296a5361cf04d02ce720d32ec5',
r: '0x09ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9c',
s: '0x440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428',
v: '0x25',
rawTransaction: '0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'
}
Просто используйте rawTransaction
.
Я нашел способ, используя pyethereum lib.
Кстати, эта библиотека требует минимального обслуживания и не встраивается в большинство ОС.
Вот пример кода для этого:
from libs.pyethereum.ethereum import transactions
from libs.pyethereum.ethereum import utils
# Create the priv keys and addresses. Addresses are returned in bytearray
key = utils.sha3("this is an insecure passphrase")
key2 = utils.sha3("37Dhsg17e92dfghKa Th!s i$ mUcH better r920167dfghjiHFGJsbcm")
addr = utils.privtoaddr(key)
addr2 = utils.privtoaddr(key2)
# Bytearray addresses
addr
'\xb8\xa1\xe7\x0b\x90\xb2\x8c\xde\x1e\xf7@+\xc2\x80\xc5\xb5\xa3W\xb4\x99'
addr2
'R~\xde {\x07"\xde\xfd\x981\x84\xcdA\x81\xbe\x82b\xdf\x01'
# Encoding the addresses in hex
addr_hex = utils.decode_addr(addr)
addr_hex
'b8a1e70b90b28cde1ef7402bc280c5b5a357b499'
addr2_hex = utils.decode_addr(addr2)
addr2_hex
'527ede207b0722defd983184cd4181be8262df01'
# These addresses are better represented with a '0x' prefix
# Create a transaction using key (address 1 priv key) and addr2 in bytearray
tx = transactions.Transaction(0, 1000, 100000, addr2, 56789000, "").sign(key)
tx.to_dict()
{'nonce': 0,
'hash': '648f97b1127bd26e5aa2f9b19d711648cb42509f105fd1ac4c90314c60bb06b1',
'sender': '\xb8\xa1\xe7\x0b\x90\xb2\x8c\xde\x1e\xf7@+\xc2\x80\xc5\xb5\xa3W\xb4\x99',
'startgas': 100000, 'value': 56789000, 'to': 'R~\xde {\x07"\xde\xfd\x981\x84\xcdA\x81\xbe\x82b\xdf\x01',
's': 27174000365690764914673576881913711980121871729925928151256478086834586258233L,
'r': 38109765815193709364550029305417348322702924861956728590268128554533127943524L,
'v': 28L, 'data': '', 'gasprice': 1000
}
Я написал полный код Python. Не стесняйтесь использовать:
def signTransaction(to, value, privkey, nonce=0, gasPrice=20000000000, gas=21000, data=""):
from ethereum import transactions
import rlp
try:
return { 'error':False, 'sign':rlp.encode(transactions.Transaction(nonce, gasPrice, gas, to, value, data).sign(privkey)).encode('hex') }
except Exception as msg:
return { 'error':True, 'message':msg }
Вот приложение JavaScript командной строки для создания автономных транзакций. Вы также можете прочитать полное руководство в блоге .
В автономном режиме, как и в вашем личном ключе, никогда не покидает ваш компьютер
Он использует сервис etherscan.io, чтобы получить последний одноразовый номер и цену на газ.
Вы можете дополнительно предоставить вызов функции контракта и аргументы
Код:
/**
* Sign an Ethereum transaction offline.
*
*
* To run:
*
* nvm use 7.2.1
* ./node_modules/babel-cli/bin/babel-node.js --presets es2015 --plugins transform-async-to-generator ./src/offlinetx.js --private-key 0xaaaaaaaaaaaaaaaaaaa --value 0.95 --to 0xAaF2ac6b800398F671b0D24cb8FccC3897B6aE49 --api-key HHHHHHHHHHHHHHHHHHHHHH
*
*/
import Web3 from 'web3'; // https://www.npmjs.com/package/web3
import argv from 'optimist';
import {buildTx, getAddressFromPrivateKey} from './txbuilder';
import {API} from './etherscan';
let web3 = new Web3();
let _argv = argv.usage("offlinetx $0 --api-key 0x0000000 --private-key 0x00000000000000 --value 1.20 --to 0x1231231231")
.describe("value", "Transaction amount in ETH")
.describe("private-key", "32 bytes private key has hexadecimal format")
.describe("to", "Ethereum 0x address where to send")
.describe("nonce", "Nonce as hexacimal format, like 0x1")
.describe("api-key", "etherscan.io API key used to get network status")
.describe("gas-limt", "Maximum gas limit for the transaction as a hexadecmial")
.default("gas-limit", web3.toHex(200000))
.string("private-key") // Heurestics is number by default which doesn't work for bigints
.string("to")
.string("api-key")
.string("value")
.string("nonce")
.string("gas-limit")
.demand(["private-key", "value", "to"]);
async function run(argv) {
// Parse command line
let apiKey = argv["api-key"];
let privateKey = argv["private-key"];
let value = argv["value"];
let to = argv["to"];
let nonce = argv["nonce"];
let gasLimit = argv["gas-limit"];
if(!privateKey) {
console.error("No private key given");
process.exit(1);
}
if(!apiKey) {
console.error("No EtherScan.io API key given");
process.exit(1);
}
// Build EtherScan.io API wrapper object
const api = new API("https://api.etherscan.io/api", apiKey);
let fromAddress = getAddressFromPrivateKey(privateKey);
// If nonce is not given get it usig Etherscan
if(!nonce) {
nonce = await api.getTransactionCount(fromAddress);
}
let gasPrice = await api.getGasPrice();
value = web3.toHex(web3.toWei(value, "ether"));
// What goes into our transaction
let txData = {
contractAddress: to,
privateKey: privateKey,
nonce: nonce,
functionSignature: null, // TODO: Add contract call support here
functionParameters: null,
value: value,
gasLimit: gasLimit,
gasPrice: gasPrice,
};
// User readable output
let info = Object.assign({}, txData);
info.fromAddress = fromAddress;
info.gasLimitInt = parseInt(txData.gasLimit, 16);
info.gasPriceInt = parseInt(txData.gasPrice, 16);
info.weiValueInt = parseInt(txData.value, 16);
console.log("Building transaction with parameters\n", info);
let tx = buildTx(txData);
console.log("Your raw transaction is: ", tx);
console.log("Visit at https://etherscan.io/pushTx to broadcast your transaction.");
}
run(_argv.argv)
.catch(function(e) {
console.error(e);
});
тайвано