Перш, ніж продовжити, переконайтеся в тому, що Ви виконали всі кроки з налаштування.
Щоб побачити список підтримуваних контрактів і дій, введіть наступну команду:stack exec -- lorentz-contract-multisig --help
Ви також можете використовувати інструмент lorentz-contract-multisig
для генерації коду Michelson для контракту Multisig, який Ви бажаєте створити, з функцією прийому тільки одного параметра, обраного Вами.
Припустимо, ми хочемо згенерувати контракт multisig, який приймає допустимим аргументом виключно nat
. Ми можемо це зробити застосувавши наступну print-specialized
команду:
$ stack exec -- lorentz-contract-multisig GenericMultisig print-specialized --parameterType 'nat' --onelineparameter (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 };
Скрипт lorentz-contract-multisig
дозволив нам згенерувати контракт Michelson. Цей самий скрипт можна застосовувати для різних допустимих типів Michelson.
У випадку, коли ми генеруємо контракт використовуючи map зі string в int, команда виглядатиме наступним чином:
$ stack exec -- lorentz-contract-multisig GenericMultisig print-specialized \--parameterType 'map string int' --onelineparameter (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 };
Ви можете порівняти обидва виходи, що представлені вище, і побачити, куди був вставлений новий тип.
Якщо ми спробуємо згенерувати контракт використовуючи підтримуваний тип, отримаємо помилку парсингу. Інструмент lorentz-contract-multisig
виконує перевірку відповідності типів за Вас.
$ stack exec -- lorentz-contract-multisig GenericMultisig print-specialized \--parameterType 'not-a-type' --onelineParseErrorBundle {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 = ""}}CallStack (from HasCallStack):error, called at src/Lorentz/Contracts/GenericMultisig/Parsers.hs:246:29 in lorentz-contract-multisig-0.1.0.1-7nDq5hWdrcbHFov64Ydo4r:Lorentz.Contracts.GenericMultisig.Parsers
Зверніть увагу: дана секція використовує такі bash функції
Generic Multisig позволяет нам установить администраторов контракта (signerKeys
) и количество этих администраторов, которое необходимо для подписи (threshold
). На момент написания, инструмент командной строки разрешает делать администраторами только неявные учетные записи tz1
, хотя контракт разрешает также учетные записи, созданные KT1
.
Generic Multisig дозволяє нам встановити адміністраторів контракту (signerKeys
) і кількість цих адміністраторів, яке необхідно для підпису (threshold
). На момент написання, інструмент командного рядка дозволяє робити адміністраторами тільки неявні облікові записи tz1
, хоча контракт дозволяє також облікові записи, створені KT1
.
Щоб згенерувати Майкельсон для початкового зберігання, наприклад для двох адмінів:
$ stack exec -- lorentz-contract-multisig GenericMultisig init-specialized \--threshold 1 --signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]"Pair 0 (Pair 1 { "edpkuPTVBFtbYd6gZWryXypSYYq6g7FvyucwphoU78T1vmGkbhj6qb"; "edpkvCHgVArnZo9RTP4P6euLTyhE89u73CYjBgsP4wEJbj4quao9oR" })
Зверніть увагу, що для правильного аналізу списку signerKeys
ви повинні уникати лапок і розділяти їх комами і без пробілів.
У наведеній вище команді ми додали двох можливих підписують осіб і встановили поріг 1, тому, якщо ми инициализируем контракт з декількома підписами з цим сховищем, всі транзакції в ньому повинні бути підписані хоча б одним з двох адміністраторів, щоб список для транзакції став дійсним.
Якщо threshold
встановлений вище, ніж кількість адміністраторів, які можуть підписувати, видається помилка, оскільки неможливо мати більше підписів адміністраторів, ніж зазначено в списку signerKeys
:
$ stack exec -- lorentz-contract-multisig GenericMultisig init-specialized \--threshold 2 --signerKeys "[\"$(get_public_key bob)\"]"threshold is greater than the number of signer keysCallStack (from HasCallStack):error, called at src/Lorentz/Contracts/GenericMultisig/CmdLnArgs.hs:302:13 in lorentz-contract-multisig-0.1.0.1-7nDq5hWdrcbHFov64Ydo4r:Lorentz.Contracts.GenericMultisig.CmdLnArgs
Используя команды, которые мы видели выше, теперь мы можем создать наш контракт, используя tezos-client
, а также контракт и начальное хранилище, которые мы сгенерировали. Мы создадим контракт MultisigNat
с двумя администраторами, Бобом и Алисой, и разрешающий только тип параметров nat
.
Використовуючи команди, які ми бачили вище, тепер ми можемо створити наш контракт, використовуючи tezos-client
, а також контракт і початкова сховище, які ми згенерували. Ми створимо контракт MultisigNat
з двома адміністраторами, Бобом і Алісою, що дозволяє тільки тип параметрів nat
.
$ tezos-client --wait none originate contract MultisigNat transferring 0 from \$BOB_ADDRESS running "$(stack exec -- lorentz-contract-multisig GenericMultisig \print-specialized --parameterType 'nat' --oneline)" \--init "$(stack exec -- lorentz-contract-multisig GenericMultisig \init-specialized --threshold 1 \--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]")" \--burn-cap 1.14Waiting for the node to be bootstrapped before injection...Current head: BLzWwsRQcRsp (timestamp: 2020-07-09T16:31:42-00:00, validation: 2020-07-09T16:32:10-00:00)Node is bootstrapped, ready for injecting operations.Estimated gas: 31880 units (will add 100 for safety)Estimated storage: 1140 bytes added (will add 20 for safety)Operation successfully injected in the node.Operation hash is 'oo9o8JHvRceyiUZ8DA1U3fTi8C6Nvc5mUBHxYGKTAXQa6BAddwT'NOT waiting for the operation to be included.Use commandtezos-client wait for oo9o8JHvRceyiUZ8DA1U3fTi8C6Nvc5mUBHxYGKTAXQa6BAddwT to be included --confirmations 30 --branch BLzWwsRQcRspFLWG5cWZF9No5g3VSZ5jgxnuDF3omYWg7ZVbHHRand/or an external block explorer to make sure that it has been included.This sequence of operations was run:Manager signed operations:From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmFee to the baker: ꜩ0.004353Expected counter: 623986Gas limit: 31980Storage limit: 1160 bytesBalance updates:tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.004353fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.004353Origination:From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmCredit: ꜩ0Script:{ ... }Initial storage:(Pair 0(Pair 1{ "edpkuPTVBFtbYd6gZWryXypSYYq6g7FvyucwphoU78T1vmGkbhj6qb" ;"edpkvCHgVArnZo9RTP4P6euLTyhE89u73CYjBgsP4wEJbj4quao9oR" }))No delegate for this contractThis origination was successfully appliedOriginated contracts:KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3Storage size: 883 bytesPaid storage size diff: 883 bytesConsumed gas: 31880Balance updates:tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.883tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257New contract KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3 originated.Contract memorized as MultisigNat.
Тепер ми можемо зберегти адресу контракту в змінній bash:
$ MULTISIG_NAT_ADDRESS="KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3"
Контракт MultisigNat
тепер можна використовувати для управління контрактами, які приймають в якості параметрів nat
. У цьому керівництві ми збираємося використовувати приклад контракту, знайдений в репозиторії lorentz-contract-multisig
, який називається Admin42. Цей контракт вимагає, щоб адміністратор взаємодіяв з ним, і приймає nat
як параметр (точніше, тільки параметр 42
!), Тому ми можемо використовувати контракт MultisigNat
для його адміністрування.
(Додаткову інформацію по самому контракту Admin42 можна знайти в репозиторіїlorentz-contract-multisig
)
Спочатку ми створимо контракт Admin42, зробивши наш контракт MultisigNat
адміністратором.
$ tezos-client --wait none originate contract MultisigAdmin42 transferring 0 \from $BOB_ADDRESS running "$(cat admin_42.tz | tr '\n' ' ')" \--init "\"$MULTISIG_NAT_ADDRESS\"" --burn-cap 0.406Waiting for the node to be bootstrapped before injection...Current head: BLGqGwqVRJEd (timestamp: 2020-07-09T16:35:12-00:00, validation: 2020-07-09T16:35:38-00:00)Node is bootstrapped, ready for injecting operations.Estimated gas: 13516 units (will add 100 for safety)Estimated storage: 406 bytes added (will add 20 for safety)Operation successfully injected in the node.Operation hash is 'op8Swwt9bYvQ58gbGPoZijJfx94tB2pbByVSco44PXuWme8oMwT'NOT waiting for the operation to be included.Use commandtezos-client wait for op8Swwt9bYvQ58gbGPoZijJfx94tB2pbByVSco44PXuWme8oMwT to be included --confirmations 30 --branch BLGqGwqVRJEdkEF9oborwD3BQkLKVuuWRxni6FwP155s5aqxKqQand/or an external block explorer to make sure that it has been included.This sequence of operations was run:Manager signed operations:From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmFee to the baker: ꜩ0.001754Expected counter: 623987Gas limit: 13616Storage limit: 426 bytesBalance updates:tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.001754fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.001754Origination:From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmCredit: ꜩ0Script:{ parameter nat ;storage address ;code { DUP ;CDR ;SENDER ;ASSERT_CMPEQ ;DUP ;CAR ;PUSH nat 42 ;ASSERT_CMPEQ ;CDR ;NIL operation ;PAIR } }Initial storage: "KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3"No delegate for this contractThis origination was successfully appliedOriginated contracts:KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVoStorage size: 149 bytesPaid storage size diff: 149 bytesConsumed gas: 13516Balance updates:tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.149tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257New contract KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo originated.Contract memorized as MultisigAdmin42.
І збережемо адресу контракту в змінну:
$ MULTISIG_ADMIN42_ADDRESS="KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo"
Коли ми взаємодіємо з нашим контрактом MultisigNat
, ми повинні включати достатню кількість підписних ключів адміністратора, щоб відповідати нашому граничному значенню. В цьому випадку у нас є два адміністратора і поріг 1, тому Боб або Аліса повинні підписати будь-яку транзакцію, яка викликає цей контракт, в іншому випадку вона буде відхилена.
Кроки для підписання:
Генерація байтів
Підписання байтів
Збереження підпису
Запуск транзакції за допомогою підпису
Давайте для початку підпишемо операцію як Аліса.
Нам знадобиться ідентифікатор ланцюжка, який ми можемо отримати з RPC:
$ tezos-client rpc get /chains/main/chain_id"NetXjD3HPJJjmcd"
Встановимо bash змінну для ідентифікатора ланцюжка:
$ CHAIN_ID="NetXjD3HPJJjmcd"
Спочатку ми сгенерируемо байти для підпису за допомогою інструменту orentz-contract-multisig
.
$ stack exec -- lorentz-contract-multisig GenericMultisig run-multisig \--target-parameterType 'nat' --target-parameter '42' \--target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 0 --signatures "Nothing" \--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" --chainId $CHAIN_ID"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000005050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00"
Давайте розберемося з цим.
target-parameterType
: Ми вже знаємо, що наш MultisigNat
і MultisigAdmin42
контракти приймають параметр типу nat
.
target-parameter
: MultisigAdmin42 дозволяє відправляти тільки значення параметра 42
, тому ми передамо це як наш цільової параметр.
target-contract
: Наша кінцева мета - відправити параметр в $MULTISIG_ADMIN42_ADDRESS
, так що це наша ціль.
multisig-contract
: Контракт з декількома підписами, керуючий нашим цільовим контрактом - це $MULTISIG_NAT_ADDRESS
.
counter
: Оскільки це перша транзакція, яку ми відправляємо через наш MultisigNat
контракт, наш counter
дорівнює 0. Якщо ви не знаєте правильного значення лічильника, ви можете використовувати наступну команду для отримання значення.
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)\"]"
signatures
: Зараз ми нічого не підписуємо, тому аргумент "Nothing"
. Ще через пару кроків ми передамо сюди список підписів.
signerKeys
: Це той же самий список ключів, з якими ви створили контракт (в тому ж порядку!). Як бонус функція get-counter-specialized
, описана в маркері counter
, підтвердить, що список відкритих ключів, які у вас є, відповідає списку ключів в сховищі.
chainId
: Це ідентифікатор ланцюжка, в який ми відправляємо. Включення його в сигнатуру запобігає атаці повторного відтворення в різних ланцюжках.
Тепер візьмемо байти, згенеровані за допомогою останньої команди, і підпишемо їх як Аліса.
$ tezos-client sign bytes \"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000005050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00" \for aliceSignature: edsigtczKcLhrkFsRKhp9cUPdbv19z9g9ZUmKkHXLA42UJMJDJ2nQypNK2iwzbrGM2HHDQR5cGYSpyVPctSkM8jAC1zHGEKyVGc
І збережемо підпис
$ OPERATION_SIGNATURE="edsigtczKcLhrkFsRKhp9cUPdbv19z9g9ZUmKkHXLA42UJMJDJ2nQypNK2iwzbrGM2HHDQR5cGYSpyVPctSkM8jAC1zHGEKyVGc"
Тепер ми збираємося знову використовувати інструмент 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'
$ tezos-client --wait none transfer 0 from $BOB_ADDRESS to $MULTISIG_NAT_ADDRESS \--arg "$(stack exec -- lorentz-contract-multisig \GenericMultisig run-multisig --target-parameterType 'nat' \--target-parameter '42' --target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 0 \--signatures "Just[Nothing,Just\"$OPERATION_SIGNATURE\"]" \--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" \--chainId $CHAIN_ID)" --burn-cap 0.000001Waiting for the node to be bootstrapped before injection...Current head: BMUPZBFduaBY (timestamp: 2020-07-09T16:37:12-00:00, validation: 2020-07-09T16:37:28-00:00)Node is bootstrapped, ready for injecting operations.Estimated gas: 46362 units (will add 100 for safety)Estimated storage: no bytes addedOperation successfully injected in the node.Operation hash is 'ooqtqmu4MyKzS5Hw7TzBjvcS9B7KMVwQ8x846tPrLsqoXwq3BJM'NOT waiting for the operation to be included.Use commandtezos-client wait for ooqtqmu4MyKzS5Hw7TzBjvcS9B7KMVwQ8x846tPrLsqoXwq3BJM to be included --confirmations 30 --branch BMUPZBFduaBYE2SfjHkUK8NqfX3UVrKwCR3Q6ffMMmC3puVM5Fyand/or an external block explorer to make sure that it has been included.This sequence of operations was run:Manager signed operations:From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmFee to the baker: ꜩ0.005069Expected counter: 623988Gas limit: 46462Storage limit: 0 bytesBalance updates:tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.005069fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.005069Transaction:Amount: ꜩ0From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmTo: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3Parameter: (Pair (Pair 0 (Left (Pair 42 "KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo"))){ None ;Some "edsigtczKcLhrkFsRKhp9cUPdbv19z9g9ZUmKkHXLA42UJMJDJ2nQypNK2iwzbrGM2HHDQR5cGYSpyVPctSkM8jAC1zHGEKyVGc" })This transaction was successfully appliedUpdated storage:(Pair 1(Pair 1{ 0x00622ace8f1d06165b951d0362624033e6f6eb5650c45290ff0ddbff6055d2caa1 ;0x00cc80ab168b04973d9e1f9d4d2248b077a9250d3bce750b2735b4818a7b9bb7d3 }))Storage size: 883 bytesConsumed gas: 32580Internal operations:Transaction:Amount: ꜩ0From: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3To: KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVoParameter: 42This transaction was successfully appliedUpdated storage: 0x0198716bd8c37c014c606841e5f7398ed70d99a6a900Storage size: 149 bytesConsumed gas: 13782
Тепер, коли ми побачили, як виглядає підписання транзакції від імені Аліси, давайте подивимося, як це виглядає, коли у нас є обидві особи с правом підпису.
Кроки дуже схожі на підписання з одного стороною підписання, але повторюються для кожної сторони підписання.
Спочатку ми генеруємо нові байти. Ми не можемо використовувати байти, згенеровані на останньому кроці, тому що тепер лічильник збільшився, оскільки ми вже відправили транзакцію в контракт MultisigNat
.
$ stack exec -- lorentz-contract-multisig GenericMultisig run-multisig \--target-parameterType 'nat' --target-parameter '42' \--target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 1 --signatures "Nothing" \--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" --chainId $CHAIN_ID"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000105050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00"
Тепер Аліса підпише ці нові байти, і ми збережемо підпис як ALICE_SIGNATURE
.
$ tezos-client sign bytes \"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000105050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00" \for aliceSignature: edsigu2ay8M6gXj2LqBmc3fJ7tMDuNP8ExiCBMFjBsi3sPSFWR8SWERNaymMqAivm9aWVAWLwiqu4qYMtBKp7B7oujM8DLxC5BM$ ALICE_SIGNATURE="edsigu2ay8M6gXj2LqBmc3fJ7tMDuNP8ExiCBMFjBsi3sPSFWR8SWERNaymMqAivm9aWVAWLwiqu4qYMtBKp7B7oujM8DLxC5BM"
І Боб зробить те ж саме. Ми збережемо його підпис як BOB_SIGNATURE
$ tezos-client sign bytes \"0x05070707070a000000049caecab90a000000160198716bd8c37c014c606841e5f7398ed70d99a6a9000707000105050707002a0a0000001601d55850d12efa417a6d53f8290f027c2650390aef00" \for bobSignature: edsigtvraShNmfMppX65BDsJuaWjasWPie9qfNyTBHwGD2kyZMe7atTvm5CULseNSD4uKY2bzzGvQDq7Jks8yFp4DRdb9t5FKX4$ BOB_SIGNATURE="edsigtvraShNmfMppX65BDsJuaWjasWPie9qfNyTBHwGD2kyZMe7atTvm5CULseNSD4uKY2bzzGvQDq7Jks8yFp4DRdb9t5FKX4"
$ tezos-client --wait none transfer 0 from $BOB_ADDRESS to $MULTISIG_NAT_ADDRESS \--arg "$(stack exec -- lorentz-contract-multisig \GenericMultisig run-multisig --target-parameterType 'nat' \--target-parameter '42' --target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 1 \--signatures "Just[Just\"$BOB_SIGNATURE\",Just\"$ALICE_SIGNATURE\"]" \--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key alice)\"]" --chainId $CHAIN_ID)" \--burn-cap 0.000001Waiting for the node to be bootstrapped before injection...Current head: BLkZFogRt69q (timestamp: 2020-07-09T16:39:12-00:00, validation: 2020-07-09T16:39:32-00:00)Node is bootstrapped, ready for injecting operations.Estimated gas: 47004 units (will add 100 for safety)Estimated storage: no bytes addedOperation successfully injected in the node.Operation hash is 'op3zyuj5wFPxyyrLAicv99DBWxHdAWU9obAwmGPEULj5gy3bEUq'NOT waiting for the operation to be included.Use commandtezos-client wait for op3zyuj5wFPxyyrLAicv99DBWxHdAWU9obAwmGPEULj5gy3bEUq to be included --confirmations 30 --branch BLkZFogRt69qpkNRupifySnJfiPZTpoPTRn2SfgEDwsaK4xQCoXand/or an external block explorer to make sure that it has been included.This sequence of operations was run:Manager signed operations:From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmFee to the baker: ꜩ0.005237Expected counter: 623989Gas limit: 47104Storage limit: 0 bytesBalance updates:tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.005237fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,269) ... +ꜩ0.005237Transaction:Amount: ꜩ0From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHmTo: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3Parameter: (Pair (Pair 1 (Left (Pair 42 "KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVo"))){ Some "edsigtvraShNmfMppX65BDsJuaWjasWPie9qfNyTBHwGD2kyZMe7atTvm5CULseNSD4uKY2bzzGvQDq7Jks8yFp4DRdb9t5FKX4" ;Some "edsigu2ay8M6gXj2LqBmc3fJ7tMDuNP8ExiCBMFjBsi3sPSFWR8SWERNaymMqAivm9aWVAWLwiqu4qYMtBKp7B7oujM8DLxC5BM" })This transaction was successfully appliedUpdated storage:(Pair 2(Pair 1{ 0x00622ace8f1d06165b951d0362624033e6f6eb5650c45290ff0ddbff6055d2caa1 ;0x00cc80ab168b04973d9e1f9d4d2248b077a9250d3bce750b2735b4818a7b9bb7d3 }))Storage size: 883 bytesConsumed gas: 33222Internal operations:Transaction:Amount: ꜩ0From: KT1NUp9a8gC5xQJDi4E9hr2WRZpUxx8BQrT3To: KT1U2qHuZrKm7EwwRZ9j6XpZyd9y6VDhpQVoParameter: 42This transaction was successfully appliedUpdated storage: 0x0198716bd8c37c014c606841e5f7398ed70d99a6a900Storage size: 149 bytesConsumed gas: 13782
Ми успішно підписали контракт з декількома адміністраторами!
Якщо хтось, хто не є адміністратором, спробує підписатися, ми отримаємо помилку моделювання трансферу. Давайте спробуємо використовувати цей контракт з декількома підписами, щоб підписатися від імені Фреда.
$ stack exec -- lorentz-contract-multisig GenericMultisig run-multisig \--target-parameterType 'nat' --target-parameter '42' \--target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 4 --signatures "Nothing" \--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key fred)\"]" --chainId $CHAIN_ID"0x05070707070a000000049caecab90a0000001601e434087b4651ce2e3132592129765f42427bde9d000707000405050707002a0a000000160122d24b94f44833a82467937ddf66a5a8960a28b200"$ tezos-client sign bytes \"0x05070707070a000000049caecab90a0000001601e434087b4651ce2e3132592129765f42427bde9d000707000405050707002a0a000000160122d24b94f44833a82467937ddf66a5a8960a28b200" \for fredSignature: edsigu3vWQjfgAH63MbXDx2Tv6j1DQ4x73Zebhvfcqg3Vw9rzaG1j6LUFPPVr9dFVySS9BPwYf5323ECRETLBcgFWyqazDcJN6z$ FRED_SIGNATURE="edsigu3vWQjfgAH63MbXDx2Tv6j1DQ4x73Zebhvfcqg3Vw9rzaG1j6LUFPPVr9dFVySS9BPwYf5323ECRETLBcgFWyqazDcJN6z"$ tezos-client --wait none transfer 0 from $BOB_ADDRESS to $MULTISIG_NAT_ADDRESS \--arg "$(stack exec -- lorentz-contract-multisig \GenericMultisig run-multisig --target-parameterType 'nat' \--target-parameter '42' --target-contract "\"$MULTISIG_ADMIN42_ADDRESS\"" \--multisig-contract "$MULTISIG_NAT_ADDRESS" --counter 4 \--signatures "Just[Just\"$BOB_SIGNATURE\",Just\"$FRED_SIGNATURE\"]" \--signerKeys "[\"$(get_public_key bob)\",\"$(get_public_key fred)\"]" --chainId $CHAIN_ID)" \--burn-cap 0.000001CallStack (from HasCallStack):error, called at src/Lorentz/Contracts/GenericMultisig/CmdLnArgs.hs:397:25 in lorentz-contract-multisig-0.1.0.1-7nDq5hWdrcbHFov64Ydo4r:Lorentz.Contracts.GenericMultisig.CmdLnArgsempty expressionFatal error:transfer simulation failed
Зверніть увагу, що передача не вдалася через «надано недійсний підпис». Контракт передбачає, що відкритий ключ Аліси буде перебувати в signerKeys
з індексом 1, а її підпис (або Nothing
) буде надана в списку підписів з індексом 1. Однак, в нашій спробі взяти під контроль контракт від імені Фреда, ми замінили її відкритий ключ і підпис. Однак контракт бачить це і не приймає виклик.
Матеріали розроблені TQ Tezos перекладені українською мовою Tezos Ukraine