Как вызвать эту функцию солидности с помощью Web3js при выполнении контракта?

Я новичок в эфириуме.
Я определенно борюсь с последними 4 параметрами этой функции, поэтому я задаю проблему напрямую.

mapping(address => uint256) nonces;
/*
 * Proxy transfer token. When some users of the ethereum account has no ether,
 * he or she can authorize the agent for broadcast transactions, and agents may charge agency fees
 * @param _from
 * @param _to
 * @param _value
 * @param fee
 * @param _v
 * @param _r
 * @param _s
 */
function transferProxy(address _from, address _to, uint256 _value, uint256 _fee,
    uint8 _v,bytes32 _r, bytes32 _s) public transferAllowed(_from) returns (bool){

    if(balances[_from] < _fee + _value) revert();

    uint256 nonce = nonces[_from];
    bytes32 h = keccak256(_from,_to,_value,_fee,nonce);
    if(_from != ecrecover(h,_v,_r,_s)) revert(); // THE PROBLEM I’m STUCK ON SEVERAL HOURS IS HERE.

    if(balances[_to] + _value < balances[_to]
        || balances[msg.sender] + _fee < balances[msg.sender]) revert();
    balances[_to] += _value;
    Transfer(_from, _to, _value);

    balances[msg.sender] += _fee;
    Transfer(_from, msg.sender, _fee);

    balances[_from] -= _value + _fee;
    nonces[_from] = nonce + 1;
    return true;
}
  • Во-первых, keccak256 обычно принимает только один аргумент (данные для хеширования). Я понятия не имею, что делает использование нескольких параметров. Добавление данных? Если да, то как? Хэширование хэшей? все сразу или перефразировать после каждого результата?
  • Во-вторых, я думаю, что для того, чтобы получить, _vмне нужно использовать web3.eth.sign с web3.eth.sign("0x395BE1C1Eb316f82781462C4C028893e51d8b2a5",keccak256("data")). Но если это не так, я не знаю, что мне нужно использовать
  • В-третьих, нет представления о том, _rо чем.
  • В-четвертых, я думаю, чтобы понять, _sчто это обратный вызов HTTP (прочитав документацию). Но кажется, что я не могу просто оставить его равным 0, так как я не знаю, что вызывать.
  • И САМОЕ СЛОЖНОЕ. Как точно определить параметры nonce в keccak256  ? (даже если я понятия не имею, как это назвать), потому что мне трудно понять, что mapping(address => uint256) nonces;и uint256 nonce = nonces[_from];на самом деле делать. И, очевидно, мне нужно знать значение, чтобы установить_v _r _s

Ответы (2)

Так что у тебя есть

Mapping(address => uint256) nonces означает, что значение uint256 связано с адресом. Позволь мне привести пример

Предположим, у вас есть адрес 0xa1bc и вы хотите сопоставить какое-то значение с этим адресом, пусть значение будет 1234. Вот как это делается

nonces["0xa1bc"] = 1234;

и получить значение, связанное с адресом

uint256 temp = nonces["0xa1bc"]

Здесь я присвоил значение temp, поэтому temp будет 1234. Если сопоставление отсутствует, значение будет 0 (ноль).

Вы можете увидеть именно такое поведение в функции transferProxy ,

uint256 одноразовый номер = одноразовый номер[_from];

nonce[_from] = одноразовый номер + 1;

Итак, в функции сначала читается одноразовый номер, связанный с адресом _from, выполняется какая-то работа и, наконец, увеличивается одноразовый номер на единицу и сохраняется по тому же адресу _from.

Теперь, переходя к вашей следующей проблеме с _v, _r и _s,

Вы правы насчет web3.eth.sign . Вы можете подписать часть сообщения с помощью web3.eth.sign(data, privatekey) и его варианта. Это даст вам объект подписи. Эту сигнатуру можно разложить на v, r и s. Итак, как вы можете получить эти значения? Обращать внимание.

знак переменной = web3.eth.sign (данные, закрытый ключ);

вар v = знак.v;

вар г = знак.г;

вар с = знак.с;

Эти v, r и s являются значениями, которые вам нужно отправить в функцию TransferProxy в контракте.

Итак, в основном, зачем вам нужны эти значения? Там вы можете увидеть функцию ecrecover , которая принимает эти значения в качестве параметров. Это встроенная функция Solidity. Он дает адрес пользователя, подписавшего данные. Здесь h — хэш данных, которые вы хотите подписать.

Но здесь мы видим, что вы не отправили хеш h контракту. Почему? Потому что вы можете создать исходное сообщение с данными, представленными в самом контракте. И это исходное сообщение _from,_to,_value,_fee,nonce . Это означает, что на стороне клиента вы сохранили или знали эти значения заранее.

var sign = web3.eth.sign(_from+_to+_value+_fee+nonce, privatekeyOf_from);

Итак, вызов функции контракта на лицевой стороне будет выглядеть так:

ContractInstance.transferProxy.sendTransaction(от, до, значение, плата, одноразовый номер, v, r, s, {от:.....});

if(_from != ecrecover(h,_v,_r,_s)) revert(); гарантирует, что пользователь с адресом _from действительно подписал данные или нет. Если не отменить (отменить изменения) транзакцию.

Что касается вашего первого вопроса, несколько параметров будут объединены, а затем хешированы.

Итак, каково будет значение nonce в первый раз, когда я звоню для отправки и получения с одним и тем же адресом 0x395BE1C1Eb316f82781462C4C028893e51d8b2a5?
в этом случае значение будет равно 0. значения по умолчанию: 0, false для типов int, boolean соответственно.
Еще кое-что. Как преобразовать параметры в ожидаемый тип Solidity?
Просто отправьте эти значения как есть. адрес и значение в байтах будут шестнадцатеричными. Если вы отправляете жестко закодированные (не назначенные некоторым переменным) значения, тогда окружайте адрес и байты кавычками.
В настоящее время все находится в строке. Я полагаю, что не могу просто объединить строковые значения для keccak256.
посмотрите на функции web3.util.sha3 или web3.util.soliditySha3
Также обратите внимание, что web3.js добавляет к тексту префикс данных, которые нужно хэшировать. Вот почему хэш не совпадает во внешнем интерфейсе и в контракте
etherscan.io/tx/… Я явно сделал что-то не так. По этому адресу ничего нет (менее 10 долларов). Я готов сбросить приватный ключ по этому поводу.

Во-первых, keccak256 обычно принимает только один аргумент (данные для хеширования). Я понятия не имею, что делает использование нескольких параметров. Добавление данных? Если да, то как? Хэширование хэшей? все сразу или перефразировать после каждого результата?

Из документов в Solidity:

keccak256(...) возвращает (bytes32): вычислить хэш Ethereum-SHA-3 (Keccak-256) (плотно упакованных) аргументов

Следовательно, данные для хеширования представляют собой плотно упакованные параметры, (_from,_to,_value,_fee,nonce)поэтому keccak256(_from,_to,_value,_fee,nonce)вычисляется хэш бинарного слова, полученного путем объединения всех этих пяти параметров.

Во-вторых, я думаю, что для получения _v мне нужно использовать web3.eth.sign с web3.eth.sign("0x395BE1C1Eb316f82781462C4C028893e51d8b2a5",keccak256("data")). Но если это не так, я не знаю, что мне нужно использовать. Третий, понятия не имеет о _r. В-четвертых, я думаю, чтобы понять, что _s относится к обратному вызову HTTP (прочитав документацию). Но кажется, что я не могу просто оставить его равным 0, так как я не знаю, что вызывать.

Эти параметры получены из подписи. При подписании web3 транзакция предоставляет подпись и параметры r, s и v. Эти параметры также могут быть получены из самой подписи, см. документацию web3 о том, как получить r, s и v, а также этот ответ

И САМОЕ СЛОЖНОЕ. Как точно определить параметры nonce в keccak256? (даже если я понятия не имею, как это назвать), потому что мне трудно понять, что такое отображение (адрес => uint256) nonces; и uint256 nonce = nonces[_from]; действительно. И, очевидно, мне нужно знать значение, чтобы установить _v _r _s

отображение принимает в качестве входных данных адрес и возвращает число, это число является одноразовым номером. Поэтому nonce[_from]запрашивает одноразовый номер для адреса _from. Это одноразовое значение в основном является счетчиком, который увеличивается каждый раз, когда транзакция выполняется с адреса _from.

Надеюсь это поможет.

Объединяя параметры, keccak256вы имеете в виду конкатенацию? Если да, то в байте или в строке?
the mapping takes as input an address and returns a number, that number is the nonce. Therefore, nonce[_from] is requesting the nonce for the address _from. This nonce value is basically a counter that increments every time a transaction is executed from the address _from.Это не говорит о том, как я получаю одноразовый номер для хеширования.
Да, означает, что они тесно связаны, что означает, что шестнадцатеричное значение каждой переменной в соответствии с типом объединяется.
Переменная nonce вычисляется на стороне майнера. Как мне вычислить это с помощью Javascript? Или мне действительно нужно заморачиваться, чтобы получить его для параметров ecrecover?
web3.eth.personal.ecRecoverесли для вычисления хеша. Требуется ли web3.eth.sign для обратного?
Вы можете получить текущий одноразовый номер для своей учетной записи, используя nonce = w3.eth.getTransactionCount('your account address'). Теперь sign подпишет сообщение и даст вам значения r, s и v. ecrecover in Solidity восстановит адрес учетной записи, которая инициирует транзакцию. В вашем коде это восстановление адреса является доказательством того, что подпись действительна. Надеюсь это поможет.
У меня аналогичная проблема с этим вопросом . Но проблема в том, что я не могу изменить смарт-контракт.