[Tech] — AccountKey Weigthed MultiSig

Tech At CHANNEL-iN
@CHANNEL-iN
Published in
9 min readJan 12, 2024

이번 시간에는 저와 함께 AccountKey Weighted MultiSig에 대해서 알아봅시다.

목차

  1. AccountKey Weighted MultiSig 란?🤔
  2. 사용법

1. AccountKey Weighted MultiSig 란?🤔

AccountKey Weighted Multisig 어감이 상당히 어렵게 느껴질 수 있습니다.

하지만 조금씩 뜯어가면서 이해해 봅시다.

AccountKey란 무엇일까요?

지갑 주소에는 키가 있습니다 공개키, 개인키 이런 게 있죠?

“이런 형식이 어떤 식으로 이루어져 있어? “를 의미합니다.

가장 크게 Legacy 방식 Public 방식이 있습니다.

Legacy 방식과 Public 방식은

여기에 자세히 포스팅하였으니 보시면 이해하기 쉬울 겁니다.

그럼 AccountKeyWeightedMultiSig 란 AccountKey 형식이

WeightedMultiSig 방식을 의미합니다.

그럼 WeightedMultiSig 란 무엇일까요?

Weighted : 가중치 ( 중요도)

Multi : 다중

Sig : 서명

즉 다중 서명을 하는데 중요도가 포함되어 있는 다중 서명을 의미합니다.

아직까지 애매모호하죠? 코드와 함께 이해해 봅시다.

전체코드

// AccountKeyWeightedMultiSig
// https://docs.klaytn.foundation/content/klaytn/design/accounts#accountkeyweightedmultisig

const { ethers } = require("ethers");

const { Wallet, TxType, AccountKeyType, parseKlay } = require("@klaytn/ethers-ext");

const senderAddr = "Your Sender Address";
const senderNewPriv1 = "Sender New Private Key1";
const senderNewPriv2 = "Sender New Private Key2";
const senderNewPriv3 = "Sender New Private Key3";
const recieverAddr = "Receiver Address";

const provider = new ethers.providers.JsonRpcProvider("https://public-en-baobab.klaytn.net");
const wallet1 = new Wallet(senderAddr, senderNewPriv1, provider);
const wallet2 = new Wallet(senderAddr, senderNewPriv2, provider);
const wallet3 = new Wallet(senderAddr, senderNewPriv3, provider);

async function updateAccount() {
const pub1 = ethers.utils.computePublicKey(senderNewPriv1, true);
const pub2 = ethers.utils.computePublicKey(senderNewPriv2, true);
const pub3 = ethers.utils.computePublicKey(senderNewPriv3, true);
console.log({ pub1, pub2, pub3 });

const tx = {
type: TxType.AccountUpdate,
from: senderAddr,
gasLimit: 1000000,
key: {
type: AccountKeyType.WeightedMultiSig,
threshold: 2,
keys: [
[1, pub1],
[1, pub2],
[1, pub3],
]
}
};


const populatedTx = await wallet1.populateTransaction(tx);
const rawTx1 = await wallet1.signTransaction(populatedTx);
console.log("rawTx1", rawTx1);

const rawTx2 = await wallet2.signTransaction(rawTx1);
console.log("rawTx2", rawTx2);

const sentTx3 = await wallet3.sendTransaction(rawTx2);
console.log("sentTx3", sentTx3);

const receipt = await sentTx3.wait();
console.log("receipt", receipt);
}




async function main() {
await updateAccount();
}
main().catch(console.error);

저희는 Web3Klaytn을 이용해야 하기 때문에 필요한 라이브러리를 가져옵니다.

const { ethers } = require("ethers");

const { Wallet, TxType, AccountKeyType, parseKlay } = require("@klaytn/ethers-ext");

다중 서명을 위해 필요한 지갑 주소랑 여러 명의 개인키를 가져옵니다.

const senderAddr = "Your Sender Address";
const senderNewPriv1 = "Sender New Private Key1";
const senderNewPriv2 = "Sender New Private Key2";
const senderNewPriv3 = "Sender New Private Key3";
const recieverAddr = "Receiver Address";

네트워크를 사용하기 위해 provider를 들고 와줍니다.

const provider = new ethers.providers.JsonRpcProvider("https://public-en-baobab.klaytn.net");

sender 지갑 주소에 개인키와 provider를 넣어서 새로운 지갑 객체를 생성해 줍니다.

const wallet1 = new Wallet(senderAddr, senderNewPriv1, provider);
const wallet2 = new Wallet(senderAddr, senderNewPriv2, provider);
const wallet3 = new Wallet(senderAddr, senderNewPriv3, provider);

AccountKey를 업그레이드해주는 함수를 만들어봅시다.

async function updateAccount() { 

}

개인키를 사용해 공개키를 만들어봅시다.

async function updateAccount() { 


const pub1 = ethers.utils.computePublicKey(senderNewPriv1, true);
const pub2 = ethers.utils.computePublicKey(senderNewPriv2, true);
const pub3 = ethers.utils.computePublicKey(senderNewPriv3, true);
console.log({ pub1, pub2, pub3 });

}

트랜잭션 객체를 생성합니다.

  const tx = {
// 이 트랜잭션의 타입은 AccountUpdate 타입입니다.
type: TxType.AccountUpdate,

// senderAddress 로부터 생성이 됩니다.
from: senderAddr,

// gasLimit은 십만입니다.
gasLimit: 1000000,

// AccountKey의 타입을 WeightedMultiSig로 정해줍니다
key: {
type: AccountKeyType.WeightedMultiSig,

// 최소 서명자 수를 의미합니다.
threshold: 2,

// pub은 공개키를 의미하고 1은 Weighted(가중치)를 의미합니다
// 즉 더욱더 중요한(영향력이 있는) 서명자를 지정할 수 있습니다.
keys: [
[1, pub1],
[1, pub2],
[1, pub3],
]
}
};

위에서 설정한 트랜잭션을 지갑에 할당해 줍니다.

const populatedTx = await wallet1.populateTransaction(tx);

실질적으로 트랜잭션 객체를 서명하는 코드입니다.

  const rawTx1 = await wallet1.signTransaction(populatedTx);

서명이 되어있는 지갑 1의 정보를 받아서 다시 지갑 2에서도 서명을 합니다.

  const rawTx2 = await wallet2.signTransaction(rawTx1);

마지막 지갑은 지갑 1 , 지갑 2에 정보를 모두 받아 최종적으로 지갑에 트랜잭션을 보냅니다.

  const sentTx3 = await wallet3.sendTransaction(rawTx2);

트랜잭션까지 모두 보냈으면
KlayScope에서 senderAddress의 Account Key가
MultiSig로 바뀌었는지 확인해 보세요.

예제코드

오늘도 유익한 글이 되셨으면 좋겠습니다 감사합니다.

--

--