Создание и использование

Генерация специализированного кода контракта с несколькими подписями

Прежде чем продолжить, убедитесь, что вы уже выполнили все шаги по настройке.
Чтобы увидеть список поддерживаемых контрактов и действий, запустите:stack exec -- lorentz-contract-multisig --help
Вы можете использовать инструмент lorentz-contract-multisig для генерации действительного Майкельсона для контракта с несколькими подписями, который вы хотите создать, специализированного для приема только указанного вами параметра.
Предположим, мы хотим сгенерировать контракт с несколькими подписями, который принимает только nat в качестве допустимого аргумента. Мы можем сделать это с помощью специальной print-specialized команды следующим образом:
1
$ stack exec -- lorentz-contract-multisig GenericMultisig print-specialized --parameterType 'nat' --oneline
2
3
parameter (pair (pair (nat :counter) (or :action (pair nat (contract nat)) (pair (nat :threshold) (list :keys key)))) (list :sigs (option signature)));storage (pair nat (pair nat (list key)));code { CAST (pair (pair (pair nat (or (pair nat (contract nat)) (pair nat (list key)))) (list (option signature))) (pair nat (pair nat (list key))));DUP;CAR;DIP { CDR };DIP { };PUSH mutez 0;AMOUNT;COMPARE;EQ;IF { } { PUSH string "Some tokens were sent to this contract outside of a unit entry point.";FAILWITH };SWAP;DUP;DIP { SWAP };DIP { DUP;CAR;DIP { CDR };DUP;SELF;ADDRESS;CHAIN_ID;PAIR;PAIR;PACK;DIP { DUP;CAR;DIP { CDR };DIP { SWAP } };SWAP };DUP;CAR;DIP { CDR };DIP { SWAP };COMPARE;EQ;IF { } { PUSH string "Counters do not match.";FAILWITH };DIP { SWAP };DUP;CAR;DIP { CDR };DIP { PUSH nat 0;SWAP;ITER { DIP { SWAP };SWAP;IF_CONS { IF_NONE { SWAP;DROP } { SWAP;DIP { SWAP;DIP { DIP { DIP { DUP };SWAP } };DIP 2 { DUP };DIG 2;DIP { CHECK_SIGNATURE };SWAP;IF { DROP } { FAILWITH };PUSH nat 1;ADD } } } { FAILWITH };SWAP } };COMPARE;LE;IF { } { PUSH string "Quorum not present";FAILWITH };IF_CONS { FAILWITH } { };DROP;DIP { DUP;CAR;DIP { CDR };PUSH nat 1;ADD;PAIR };IF_LEFT { DIP { };SWAP;DIP { DUP;CAR;DIP { CDR };DIP { DIP { NIL operation };PUSH mutez 0 };TRANSFER_TOKENS;CONS };SWAP } { DIP { CAR };SWAP;PAIR;NIL operation };PAIR };
Copied!
Скрипт lorentz-contract-multisig сгенерировал для нас действующий контракт Майкельсона. Мы можем сделать то же самое с любым допустимым типом Майкельсона.
Если мы сгенерируем с картой от string до int, это будет выглядеть следующим образом:
1
$ stack exec -- lorentz-contract-multisig GenericMultisig print-specialized \
2
--parameterType 'map string int' --oneline
3
4
parameter (pair (pair (nat :counter) (or :action (pair (map string int) (contract (map string int))) (pair (nat :threshold) (list :keys key)))) (list :sigs (option signature)));storage (pair nat (pair nat (list key)));code { CAST (pair (pair (pair nat (or (pair (map string int) (contract (map string int))) (pair nat (list key)))) (list (option signature))) (pair nat (pair nat (list key))));DUP;CAR;DIP { CDR };DIP { };PUSH mutez 0;AMOUNT;COMPARE;EQ;IF { } { PUSH string "Some tokens were sent to this contract outside of a unit entry point.";FAILWITH };SWAP;DUP;DIP { SWAP };DIP { DUP;CAR;DIP { CDR };DUP;SELF;ADDRESS;CHAIN_ID;PAIR;PAIR;PACK;DIP { DUP;CAR;DIP { CDR };DIP { SWAP } };SWAP };DUP;CAR;DIP { CDR };DIP { SWAP };COMPARE;EQ;IF { } { PUSH string "Counters do not match.";FAILWITH };DIP { SWAP };DUP;CAR;DIP { CDR };DIP { PUSH nat 0;SWAP;ITER { DIP { SWAP };SWAP;IF_CONS { IF_NONE { SWAP;DROP } { SWAP;DIP { SWAP;DIP { DIP { DIP { DUP };SWAP } };DIP 2 { DUP };DIG 2;DIP { CHECK_SIGNATURE };SWAP;IF { DROP } { FAILWITH };PUSH nat 1;ADD } } } { FAILWITH };SWAP } };COMPARE;LE;IF { } { PUSH string "Quorum not present";FAILWITH };IF_CONS { FAILWITH } { };DROP;DIP { DUP;CAR;DIP { CDR };PUSH nat 1;ADD;PAIR };IF_LEFT { DIP { };SWAP;DIP { DUP;CAR;DIP { CDR };DIP { DIP { NIL operation };PUSH mutez 0 };TRANSFER_TOKENS;CONS };SWAP } { DIP { CAR };SWAP;PAIR;NIL operation };PAIR };
Copied!
Вы можете сравнить два вывода выше и увидеть, где был вставлен новый тип.
Если бы мы попытались создать контракт с использованием недопустимого типа, мы бы получили ошибку синтаксического анализа. Инструмент lorentz-contract-multisig проверяет типы за вас.
1
$ stack exec -- lorentz-contract-multisig GenericMultisig print-specialized \
2
--parameterType 'not-a-type' --oneline
3
4
ParseErrorBundle {bundleErrors = FancyError 0 (fromList [ErrorCustom UnknownTypeException]) :| [], bundlePosState = PosState {pstateInput = "not-a-type", pstateOffset = 0, pstateSourcePos = SourcePos {sourceName = "parameter", sourceLine = Pos 1, sourceColumn = Pos 1}, pstateTabWidth = Pos 8, pstateLinePrefix = ""}}
5
CallStack (from HasCallStack):
6
error, called at src/Lorentz/Contracts/GenericMultisig/Parsers.hs:246:29 in lorentz-contract-multisig-0.1.0.1-7nDq5hWdrcbHFov64Ydo4r:Lorentz.Contracts.GenericMultisig.Parsers
Copied!

Создание начального хранилища

Обратите внимание: в этом разделе используются определенные здесь функции bash.
Generic Multisig позволяет нам установить администраторов контракта (signerKeys) и количество этих администраторов, которое необходимо для подписи (threshold). На момент написания, инструмент командной строки разрешает делать администраторами только неявные учетные записи tz1, хотя контракт разрешает также учетные записи, созданные KT1.
Чтобы сгенерировать Майкельсон для начального хранения, например для двух админов:
1
$ stack exec -- lorentz-contract-multisig GenericMultisig init-specialized \
2
--threshold 1 --signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]"
3
4
Pair 0 (Pair 1 { "edpkuPTVBFtbYd6gZWryXypSYYq6g7FvyucwphoU78T1vmGkbhj6qb"; "edpkvCHgVArnZo9RTP4P6euLTyhE89u73CYjBgsP4wEJbj4quao9oR" })
Copied!
Обратите внимание, что для правильного анализа списка signerKeys вы должны избегать кавычек и разделять их запятыми и без пробелов.
В приведенной выше команде мы добавили двух возможных подписывающих лиц и установили порог 1, поэтому, если мы инициализируем контракт с несколькими подписями с этим хранилищем, все транзакции в нем должны быть подписаны хотя бы одним из двух администраторов, чтобы список для транзакции стал действительным.
Если threshold установлен выше, чем количество администраторов, которые могут подписывать, выдается ошибка, поскольку невозможно иметь больше подписей администраторов, чем указано в списке signerKeys:
1
$ stack exec -- lorentz-contract-multisig GenericMultisig init-specialized \
2
--threshold 2 --signerKeys "[\"$(get_public_key bob)\"]"
3
4
threshold is greater than the number of signer keys
5
CallStack (from HasCallStack):
6
error, called at src/Lorentz/Contracts/GenericMultisig/CmdLnArgs.hs:302:13 in lorentz-contract-multisig-0.1.0.1-7nDq5hWdrcbHFov64Ydo4r:Lorentz.Contracts.GenericMultisig.CmdLnArgs
Copied!

Создание контракта с несколькими подписями с созданным Майкельсоном

Используя команды, которые мы видели выше, теперь мы можем создать наш контракт, используя tezos-client, а также контракт и начальное хранилище, которые мы сгенерировали. Мы создадим контракт MultisigNat с двумя администраторами, Бобом и Алисой, и разрешающий только тип параметров nat.
1
$ tezos-client --wait none originate contract MultisigNat transferring 0 from \
2
$BOB_ADDRESS running "$(stack exec -- lorentz-contract-multisig GenericMultisig \
3
print-specialized --parameterType 'nat' --oneline)" \
4
--init "$(stack exec -- lorentz-contract-multisig GenericMultisig \
5
init-specialized --threshold 1 \
6
--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]")" \
7
--burn-cap 1.14
8
9
Waiting for the node to be bootstrapped before injection...
10
Current head: BLzWwsRQcRsp (timestamp: 2020-07-09T16:31:42-00:00, validation: 2020-07-09T16:32:10-00:00)
11
Node is bootstrapped, ready for injecting operations.
12
Estimated gas: 31880 units (will add 100 for safety)
13
Estimated storage: 1140 bytes added (will add 20 for safety)
14
Operation successfully injected in the node.
15
Operation hash is 'oo9o8JHvRceyiUZ8DA1U3fTi8C6Nvc5mUBHxYGKTAXQa6BAddwT'
16
NOT waiting for the operation to be included.
17
Use command
18
tezos-client wait for oo9o8JHvRceyiUZ8DA1U3fTi8C6Nvc5mUBHxYGKTAXQa6BAddwT to be included --confirmations 30 --branch BLzWwsRQcRspFLWG5cWZF9No5g3VSZ5jgxnuDF3omYWg7ZVbHHR
19
and/or an external block explorer to make sure that it has been included.
20
This sequence of operations was run:
21
Manager signed operations:
22
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
23
Fee to the baker: ꜩ0.004353
24
Expected counter: 623986
25
Gas limit: 31980
26
Storage limit: 1160 bytes
27
Balance updates:
28
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.004353
29
fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.004353
30
Origination:
31
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
32
Credit: ꜩ0
33
Script:
34
{ ... }
35
Initial storage:
36
(Pair 0
37
(Pair 1
38
{ "edpkuPTVBFtbYd6gZWryXypSYYq6g7FvyucwphoU78T1vmGkbhj6qb" ;
39
"edpkvCHgVArnZo9RTP4P6euLTyhE89u73CYjBgsP4wEJbj4quao9oR" }))
40
No delegate for this contract
41
This origination was successfully applied
42
Originated contracts:
43
KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3
44
Storage size: 883 bytes
45
Paid storage size diff: 883 bytes
46
Consumed gas: 31880
47
Balance updates:
48
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.883
49
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257
50
51
New contract KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3 originated.
52
Contract memorized as MultisigNat.
Copied!
Теперь мы можем сохранить адрес контракта в переменной bash:
1
$ MULTISIG_NAT_ADDRESS="KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3"
Copied!

Администрирование второго контракта с помощью Specialized Multisig

Создание контракта Admin42

Контракт MultisigNat теперь можно использовать для управления контрактами, которые принимают в качестве параметров nat. В этом руководстве мы собираемся использовать пример контракта, найденный в репозитории lorentz-contract-multisig, который называется Admin42. Этот контракт требует, чтобы администратор взаимодействовал с ним, и принимает nat в качестве параметра (точнее, только параметр 42!), Поэтому мы можем использовать контракт MultisigNat для его администрирования.
(Дополнительную информацию о самом контракте Admin42 можно найти в репозитории lorentz-contract-multisig)
Сначала мы создадим контракт Admin42, сделав наш контракт MultisigNat администратором.
1
$ tezos-client --wait none originate contract MultisigAdmin42 transferring 0 \
2
from $BOB_ADDRESS running "$(cat admin_42.tz | tr '\n' ' ')" \
3
--init "\"$MULTISIG_NAT_ADDRESS\"" --burn-cap 0.406
4
5
Waiting for the node to be bootstrapped before injection...
6
Current head: BLGqGwqVRJEd (timestamp: 2020-07-09T16:35:12-00:00, validation: 2020-07-09T16:35:38-00:00)
7
Node is bootstrapped, ready for injecting operations.
8
Estimated gas: 13516 units (will add 100 for safety)
9
Estimated storage: 406 bytes added (will add 20 for safety)
10
Operation successfully injected in the node.
11
Operation hash is 'op8Swwt9bYvQ58gbGPoZijJfx94tB2pbByVSco44PXuWme8oMwT'
12
NOT waiting for the operation to be included.
13
Use command
14
tezos-client wait for op8Swwt9bYvQ58gbGPoZijJfx94tB2pbByVSco44PXuWme8oMwT to be included --confirmations 30 --branch BLGqGwqVRJEdkEF9oborwD3BQkLKVuuWRxni6FwP155s5aqxKqQ
15
and/or an external block explorer to make sure that it has been included.
16
This sequence of operations was run:
17
Manager signed operations:
18
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
19
Fee to the baker: ꜩ0.001754
20
Expected counter: 623987
21
Gas limit: 13616
22
Storage limit: 426 bytes
23
Balance updates:
24
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.001754
25
fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.001754
26
Origination:
27
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
28
Credit: ꜩ0
29
Script:
30
{ parameter nat ;
31
storage address ;
32
code { DUP ;
33
CDR ;
34
SENDER ;
35
ASSERT_CMPEQ ;
36
DUP ;
37
CAR ;
38
PUSH nat 42 ;
39
ASSERT_CMPEQ ;
40
CDR ;
41
NIL operation ;
42
PAIR } }
43
Initial storage: "KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3"
44
No delegate for this contract
45
This origination was successfully applied
46
Originated contracts:
47
KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo
48
Storage size: 149 bytes
49
Paid storage size diff: 149 bytes
50
Consumed gas: 13516
51
Balance updates:
52
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.149
53
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257
54
55
New contract KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo originated.
56
Contract memorized as MultisigAdmin42.
Copied!
И сохраним адрес контракта в переменной:
1
$ MULTISIG_ADMIN42_ADDRESS="KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo"
Copied!

Подписание транзакции с одним подписывающим

Когда мы взаимодействуем с нашим контрактом MultisigNat, мы должны включать достаточное количество подписывающих ключей администратора, чтобы соответствовать нашему пороговому значению. В этом случае у нас есть два администратора и порог 1, поэтому Боб или Алиса должны подписать любую транзакцию, которая вызывает этот контракт, в противном случае она будет отклонена.
Шаги для подписания:
    1.
    Генерация байтов
    2.
    Подпись байтов
    3.
    Сохранение подписи
    4.
    Запуск транзакции с помощью подписи
Давайте для начала подпишем операцию как Алиса.
Нам понадобится идентификатор цепочки, который мы можем получить из RPC:
1
$ tezos-client rpc get /chains/main/chain_id
2
3
"NetXjD3HPJJjmcd"
Copied!
Установим bash переменную для идентификатора цепочки:
1
$ CHAIN_ID="NetXjD3HPJJjmcd"
Copied!
Сначала мы сгенерируем байты для подписи с помощью инструмента orentz-contract-multisig.
1
$ stack exec -- lorentz-contract-multisig GenericMultisig run-multisig \
2
--target-parameterType 'nat' --target-parameter '42' \
3
--target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \
4
--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 0 --signatures "Nothing" \
5
--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" --chainId $CHAIN_ID
6
7
"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000005050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00"
Copied!
Давайте разберемся с этим.
    target-parameterType: Мы уже знаем, что наш MultisigNat и MultisigAdmin42 контракты принимают параметр типа nat.
    target-parameter: MultisigAdmin42 позволяет отправлять только значение параметра 42, поэтому мы передадим это как наш целевой параметр.
    target-contract: Наша конечная цель - отправить параметр в $MULTISIG_ADMIN42_ADDRESS, так что это наша цель.
    multisig-contract: Контракт с несколькими подписями, управляющий нашим целевым контрактом - это $MULTISIG_NAT_ADDRESS.
    counter: Поскольку это первая транзакция, которую мы отправляем через наш MultisigNat контракт, наш counter равен 0. Если вы не знаете правильного значения счетчика, вы можете использовать следующую команду для получения значения.
    1
    stack exec -- lorentz-contract-multisig GenericMultisig get-counter-specialized --storageText "$(tezos-client get contract storage for $MULTISIG_NAT_ADDRESS)" --signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]"
    Copied!
    signatures: Сейчас мы ничего не подписываем, поэтому аргумент "Nothing". Еще через пару шагов мы передадим сюда список подписей.
    signerKeys: Это тот же самый список ключей, с которыми вы создали контракт (в том же порядке!). В качестве бонуса функция get-counter-specialized, описанная в маркере counter, подтвердит, что список открытых ключей, которые у вас есть, соответствует списку ключей в хранилище.
    chainId: Это идентификатор цепочки, в которую мы отправляем. Включение его в сигнатуру предотвращает атаки повторного воспроизведения в разных цепочках.
Теперь возьмем байты, сгенерированные с помощью последней команды, и подпишем их как Алиса.
1
$ tezos-client sign bytes \
2
"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000005050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00" \
3
for alice
4
5
Signature: edsigtczKcLhrkFsRKhp9cUPdbv19z9g9ZUmKkHXLA42UJMJDJ2nQypNK2iwzbrGM2HHDQR5cGYSpyVPctSkM8jAC1zHGEKyVGc
Copied!
И сохраним подпись
1
$ OPERATION_SIGNATURE="edsigtczKcLhrkFsRKhp9cUPdbv19z9g9ZUmKkHXLA42UJMJDJ2nQypNK2iwzbrGM2HHDQR5cGYSpyVPctSkM8jAC1zHGEKyVGc"
Copied!
Теперь мы собираемся снова использовать инструмент lorentz-contract-multisig, но теперь мы собираемся добавить нашу подпись. Здесь следует отметить несколько моментов:
    Несмотря на то, что я отправляю $OPERATION_SIGNATURE от Алисы, я все равно могу создать транзакцию как перевод с $BOB_ADDRESS на $MULTISIG_NAT_ADDRESS. Фактически, мы могли отправить эту транзакцию из $FRED_ADDRESS, и пока у нас есть правильные подписи, он будет работать.
    Следует отметить синтаксис аргумента signatures. Структура должна быть в виде списка, который соответствует signerKeys, то есть для каждого signerKey, в подписном листе должна быть соответствующая запись. В этом случае мы имеем только подпись Алисы. Алиса - второй открытый ключ в списке signerKeys, когда мы структурируем наш список подписей, мы добавим $OPERATION_SIGNATURE , которую она подписала в качестве второй записи в списке. Поскольку Боб не подписывает, мы ничего не помещаем в его индекс в списке. Так что у нас будет "Just[Nothing,Just\"$OPERATION_SIGNATURE\"]". Если бы Боб подписывал, а Алисы не было бы, у нас было бы "Just[Just\"$OPERATION_SIGNATURE\",Nothing]". А, если бы оба подписывали, у нас было бы "Just[Just\"$BOB_SIGNATURE\",Just\"$ALICE_SIGNATURE\"]". Далее мы покажем полный пример с несколькими подписывающими сторонами.
    Мы должны указать нашу точку входа как 'mainParameter'
1
$ tezos-client --wait none transfer 0 from $BOB_ADDRESS to $MULTISIG_NAT_ADDRESS \
2
--arg "$(stack exec -- lorentz-contract-multisig \
3
GenericMultisig run-multisig --target-parameterType 'nat' \
4
--target-parameter '42' --target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \
5
--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 0 \
6
--signatures "Just[Nothing,Just\"$OPERATION_SIGNATURE\"]" \
7
--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" \
8
--chainId $CHAIN_ID)" --burn-cap 0.000001
9
10
Waiting for the node to be bootstrapped before injection...
11
Current head: BMUPZBFduaBY (timestamp: 2020-07-09T16:37:12-00:00, validation: 2020-07-09T16:37:28-00:00)
12
Node is bootstrapped, ready for injecting operations.
13
Estimated gas: 46362 units (will add 100 for safety)
14
Estimated storage: no bytes added
15
Operation successfully injected in the node.
16
Operation hash is 'ooqtqmu4MyKzS5Hw7TzBjvcS9B7KMVwQ8x846tPrLsqoXwq3BJM'
17
NOT waiting for the operation to be included.
18
Use command
19
tezos-client wait for ooqtqmu4MyKzS5Hw7TzBjvcS9B7KMVwQ8x846tPrLsqoXwq3BJM to be included --confirmations 30 --branch BMUPZBFduaBYE2SfjHkUK8NqfX3UVrKwCR3Q6ffMMmC3puVM5Fy
20
and/or an external block explorer to make sure that it has been included.
21
This sequence of operations was run:
22
Manager signed operations:
23
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
24
Fee to the baker: ꜩ0.005069
25
Expected counter: 623988
26
Gas limit: 46462
27
Storage limit: 0 bytes
28
Balance updates:
29
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.005069
30
fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.005069
31
Transaction:
32
Amount: ꜩ0
33
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
34
To: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3
35
Parameter: (Pair (Pair 0 (Left (Pair 42 "KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo")))
36
{ None ;
37
Some "edsigtczKcLhrkFsRKhp9cUPdbv19z9g9ZUmKkHXLA42UJMJDJ2nQypNK2iwzbrGM2HHDQR5cGYSpyVPctSkM8jAC1zHGEKyVGc" })
38
This transaction was successfully applied
39
Updated storage:
40
(Pair 1
41
(Pair 1
42
{ 0x00622ace8f1d06165b951d0362624033e6f6eb5650c45290ff0ddbff6055d2caa1 ;
43
0x00cc80ab168b04973d9e1f9d4d2248b077a9250d3bce750b2735b4818a7b9bb7d3 }))
44
Storage size: 883 bytes
45
Consumed gas: 32580
46
Internal operations:
47
Transaction:
48
Amount: ꜩ0
49
From: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3
50
To: KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo
51
Parameter: 42
52
This transaction was successfully applied
53
Updated storage: 0x0198716bd8c37c014c606841e5f7398ed70d99a6a900
54
Storage size: 149 bytes
55
Consumed gas: 13782
Copied!

Подписание транзакции с двумя подписывающими

Теперь, когда мы увидели, как выглядит подписание транзакции от имени Алисы, давайте посмотрим, как это выглядит, когда у нас есть оба подписывающих лица.
Шаги очень похожи на подписание с одной подписывающей стороной, но повторяются для каждой подписывающей стороны.
Сначала мы генерируем новые байты. Мы не можем использовать байты, сгенерированные на последнем шаге, потому что теперь счетчик увеличился, поскольку мы уже отправили транзакцию в контракт MultisigNat.
1
$ stack exec -- lorentz-contract-multisig GenericMultisig run-multisig \
2
--target-parameterType 'nat' --target-parameter '42' \
3
--target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \
4
--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 1 --signatures "Nothing" \
5
--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" --chainId $CHAIN_ID
6
7
"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000105050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00"
Copied!
Теперь Алиса подпишет эти новые байты, и мы сохраним подпись как ALICE_SIGNATURE.
1
$ tezos-client sign bytes \
2
"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000105050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00" \
3
for alice
4
5
Signature: edsigu2ay8M6gXj2LqBmc3fJ7tMDuNP8ExiCBMFjBsi3sPSFWR8SWERNaymMqAivm9aWVAWLwiqu4qYMtBKp7B7oujM8DLxC5BM
6
7
$ ALICE_SIGNATURE="edsigu2ay8M6gXj2LqBmc3fJ7tMDuNP8ExiCBMFjBsi3sPSFWR8SWERNaymMqAivm9aWVAWLwiqu4qYMtBKp7B7oujM8DLxC5BM"
Copied!
И Боб сделает то же самое. Мы сохраним его подпись как BOB_SIGNATURE
1
$ tezos-client sign bytes \
2
"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000105050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00" \
3
for bob
4
5
Signature: edsigtvraShNmfMppX65BDsJuaWjasWPie9qfNyTBHwGD2kyZMe7atTvm5CULseNSD4uKY2bzzGvQDq7Jks8yFp4DRdb9t5FKX4
6
7
$ BOB_SIGNATURE="edsigtvraShNmfMppX65BDsJuaWjasWPie9qfNyTBHwGD2kyZMe7atTvm5CULseNSD4uKY2bzzGvQDq7Jks8yFp4DRdb9t5FKX4"
Copied!
1
$ tezos-client --wait none transfer 0 from $BOB_ADDRESS to $MULTISIG_NAT_ADDRESS \
2
--arg "$(stack exec -- lorentz-contract-multisig \
3
GenericMultisig run-multisig --target-parameterType 'nat' \
4
--target-parameter '42' --target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \
5
--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 1 \
6
--signatures "Just[Just\"$BOB_SIGNATURE\",Just\"$ALICE_SIGNATURE\"]" \
7
--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" --chainId $CHAIN_ID)" \
8
--burn-cap 0.000001
9
10
Waiting for the node to be bootstrapped before injection...
11
Current head: BLkZFogRt69q (timestamp: 2020-07-09T16:39:12-00:00, validation: 2020-07-09T16:39:32-00:00)
12
Node is bootstrapped, ready for injecting operations.
13
Estimated gas: 47004 units (will add 100 for safety)
14
Estimated storage: no bytes added
15
Operation successfully injected in the node.
16
Operation hash is 'op3zyuj5wFPxyyrLAicv99DBWxHdAWU9obAwmGPEULj5gy3bEUq'
17
NOT waiting for the operation to be included.
18
Use command
19
tezos-client wait for op3zyuj5wFPxyyrLAicv99DBWxHdAWU9obAwmGPEULj5gy3bEUq to be included --confirmations 30 --branch BLkZFogRt69qpkNRupifySnJfiPZTpoPTRn2SfgEDwsaK4xQCoX
20
and/or an external block explorer to make sure that it has been included.
21
This sequence of operations was run:
22
Manager signed operations:
23
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
24
Fee to the baker: ꜩ0.005237
25
Expected counter: 623989
26
Gas limit: 47104
27
Storage limit: 0 bytes
28
Balance updates:
29
tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.005237
30
fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.005237
31
Transaction:
32
Amount: ꜩ0
33
From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
34
To: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3
35
Parameter: (Pair (Pair 1 (Left (Pair 42 "KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo")))
36
{ Some "edsigtvraShNmfMppX65BDsJuaWjasWPie9qfNyTBHwGD2kyZMe7atTvm5CULseNSD4uKY2bzzGvQDq7Jks8yFp4DRdb9t5FKX4" ;
37
Some "edsigu2ay8M6gXj2LqBmc3fJ7tMDuNP8ExiCBMFjBsi3sPSFWR8SWERNaymMqAivm9aWVAWLwiqu4qYMtBKp7B7oujM8DLxC5BM" })
38
This transaction was successfully applied
39
Updated storage:
40
(Pair 2
41
(Pair 1
42
{ 0x00622ace8f1d06165b951d0362624033e6f6eb5650c45290ff0ddbff6055d2caa1 ;
43
0x00cc80ab168b04973d9e1f9d4d2248b077a9250d3bce750b2735b4818a7b9bb7d3 }))
44
Storage size: 883 bytes
45
Consumed gas: 33222
46
Internal operations:
47
Transaction:
48
Amount: ꜩ0
49
From: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3
50
To: KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo
51
Parameter: 42
52
This transaction was successfully applied
53
Updated storage: 0x0198716bd8c37c014c606841e5f7398ed70d99a6a900
54
Storage size: 149 bytes
55
Consumed gas: 13782
Copied!
Мы успешно подписали контракт с несколькими администраторами!

Подписание транзакции с неавторизованной подписывающей стороной

Если кто-то, не являющийся администратором, попытается подписаться, мы получим ошибку моделирования трансфера. Давайте попробуем использовать этот контракт с несколькими подписями, чтобы подписаться от имени Фреда.
1
$ stack exec -- lorentz-contract-multisig GenericMultisig run-multisig \
2
--target-parameterType 'nat' --target-parameter '42' \
3
--target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \
4
--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 4 --signatures "Nothing" \
5
--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key fred)\"]" --chainId $CHAIN_ID
6
7
"0x05070707070a000000049caecab90a0000001601e434087b4651ce2e3132592129765f42427bde9d000707000405050707002a0a000000160122d24b94f44833a82467937ddf66a5a8960a28b200"
8
9
$ tezos-client sign bytes \
10
"0x05070707070a000000049caecab90a0000001601e434087b4651ce2e3132592129765f42427bde9d000707000405050707002a0a000000160122d24b94f44833a82467937ddf66a5a8960a28b200" \
11
for fred
12
13
Signature: edsigu3vWQjfgAH63MbXDx2Tv6j1DQ4x73Zebhvfcqg3Vw9rzaG1j6LUFPPVr9dFVySS9BPwYf5323ECRETLBcgFWyqazDcJN6z
14
15
$ FRED_SIGNATURE="edsigu3vWQjfgAH63MbXDx2Tv6j1DQ4x73Zebhvfcqg3Vw9rzaG1j6LUFPPVr9dFVySS9BPwYf5323ECRETLBcgFWyqazDcJN6z"
16
17
$ tezos-client --wait none transfer 0 from $BOB_ADDRESS to $MULTISIG_NAT_ADDRESS \
18
--arg "$(stack exec -- lorentz-contract-multisig \
19
GenericMultisig run-multisig --target-parameterType 'nat' \
20
--target-parameter '42' --target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \
21
--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 4 \
22
--signatures "Just[Just\"$BOB_SIGNATURE\",Just\"$FRED_SIGNATURE\"]" \
23
--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key fred)\"]" --chainId $CHAIN_ID)" \
24
--burn-cap 0.000001
25
26
CallStack (from HasCallStack):
27
error, called at src/Lorentz/Contracts/GenericMultisig/CmdLnArgs.hs:397:25 in lorentz-contract-multisig-0.1.0.1-7nDq5hWdrcbHFov64Ydo4r:Lorentz.Contracts.GenericMultisig.CmdLnArgs
28
29
empty expression
30
Fatal error:
31
transfer simulation failed
Copied!
Обратите внимание, что передача не удалась из-за «предоставленной недействительной подписи». Контракт предполагает, что открытый ключ Алисы будет находиться в signerKeys с индексом 1, а ее подпись (или Nothing) будет предоставлена в списке подписей с индексом 1. Однако, в нашей попытке взять под контроль контракт в качестве Фреда, мы заменили ее открытый ключ и подпись. Однако контракт видит это и не принимает вызов.
Материалы разработаны TQ Tezos переведены на русский язык Tezos Ukraine
Last modified 1yr ago