계정과 연결된 키 구조.
AccountKeyNil : 공백 키를 나타냄.
AccountKeyLegacy : 키 쌍에서 파생된 주소를 가진 계정에 사용.
키쌍에서 파생된지 어케아냐?
- 공개키를 ecrecover(txhash, txsig)로 얻기.
- 주소는 발신자입니다..???
AccountKeyPublic : 하나의 공개 키를 가진 계정에 사용
ecrecover(txhash, txsig) === 공개키?? 로 판별.
AccountKeyFail : 트랜잭션 유효성 검증 프로세스는 항상 실패하게 됨.
AccountKeyWeightedMultiSig : threshold + WeightedPublicKeys( 공개키 + 가중치 + 리스트 )
threshold : 서명시 공개키의 가중치보다 작아야함.
서명된 공개키 < WeightedPublicKey 여야함.
AccountKeyRoleBased : 역할마다 엑세스 범위를 나눈 역할 기반 키.
RoleTransaction : TxTypeAccountUpdate 이외
RoleAccountUpdate : TxTypeAccountUpdate 만
RoleFeePayer : FeePayer 트랙잭션시
🙋♂️ 발신자가 동일한 논스를 가진 두 개의 트랜잭션을 생성하면 하나만 실행된다...? 논스를 설정할 수 있다고??
기존 : 공개키 <-> 서명 (서로 파생)
클레이튼 : 공개키(키쌍) // 서명 => 서명에서 주체의 주소를 가져올 수 없음 => from(계정키)이 있는 이유.
트랜잭션 수수료 납부자의 주소와 서명이 없는 트랜잭션의 해시
🙋♂️ 서명없이 해시를 어케 만드냐?
🤖 납부자가 동의하는 서명을 하면 해시 생성됨.
🤖 약간 착불같은 느낌
SenderTxHash를 얻기 위한 방법은 트랜잭션 유형에 따라 다름
앞에 (TxType)은 생략하겠음..(너무길어)
1. LegacyTransaction : 이전에 Klaytn에 존재했던 트랜잭션 유형
FeeDelegatedValueTransfer : 사용자가 KLAY를 보내려고 할 때 사용
FeeDelegatedValueTransferMemo : 메시지와 함께 Klay를 보내려고 할때 사용
FeeDelegatedSmartContractDeploy : 수수료 위임하는 컨트랙트를 배포.
FeeDelegatedSmartContractExecution : to가 스마트 컨트랙트 계정일 때 스마트 컨트랙트를 실행하고, input에 입력된 데이터를 이용. 트랜잭션 수수료는 지정된 수수료 납부자가 지불.
FeeDelegatedAccountUpdate : 해당 계정의 키를 업데이트시 수수료 납부자가 지불.
FeeDelegatedCancel : 같은 논스를 가진 트랜잭션을 취소시 수수료 납부자가 지불.
FeeDelegatedChainDataAnchoring : 앵커링시 수수료를 납부자가 지불.
트랜잭션 비용 위임 종류와 똑같지만 Ratio 기능의 추가로 일부는 납부자가, 일부는 본인이 지불하는 기능.
Klaytn 계정의 주소와 개인 키를 포함하는 구조.
🙋♂️ 역할은 어떻게 표현하나요?
🤖 [[roleTransactionKey],[roleAccountUpdateKey],[FeePayerKey]]이런 이차원 배열로 표현.
🙋♂️ 역할은 뭐가 있나요?
🤖
🙋♂️ 보니까 키링을 월렛에 추가해주는거 같은데 왜 그러나요?
🤖 월렛에 있어야지 그때그때 또 생성하는게 아니라 한번만 만들고 계속 쓰징
서명은 wallet을 통해 할 수 있고 트랜잭션을 보낼려면 2가지 단계를 거침.
서명 (caver.wallet에 키링추가 or transction.sign )
// 키링 생성
const keyring = caver.wallet.keyring.createFromPrivateKey('0x{private key}')
caver.wallet.add(keyring)
// Create a value transfer transaction
const valueTransfer = caver.transaction.valueTransfer.create({
from: keyring.address,
to: '0x176ff0344de49c04be577a3512b6991507647f72',
value: 1,
gas: 30000,
})
// 월렛에서 서명.
await caver.wallet.sign(keyring.address, valueTransfer)
// rlp로 만들어줌.
const rlpEncoded = valueTransfer.getRLPEncoding()
// 만든 rlp 전송.
const receipt = await caver.rpc.klay.sendRawTransaction(rlpEncoding)
console.log(receipt)
// 키링 생성
const keyring = caver.wallet.keyring.createFromPrivateKey('0x{private key}')
// 트랜젝션 생성
const valueTransfer = caver.transaction.valueTransfer.create({
from: keyring.address,
to: '0x176ff0344de49c04be577a3512b6991507647f72',
value: 1,
gas: 30000,
})
// {transaction}.sign 으로 사인해줌.
await valueTransfer.sign(keyring)
// 전송~
const receipt = await caver.rpc.klay.sendRawTransaction(valueTransfer)
RLP 인코딩된 서명된 트랜잭션을 caver.rpc.klay.sendRawTransaction
을 통해 Klaytn에 전송
🙋♂️ 다른 트랜잭션 타입 왜 나누는데?
🤖 목적에 따라 최적의 트랜잭션을 제공하면 사용자가 사용하기 좋거든.
🙋♂️ 이해가 안가요
🤖 목적에 따라 거래의 유형을 바꾼다는 걸로 생각하면, 작은 금액은 "일시불"로 거래 하고 비싼 금액은 "할부"로 거래 하는걸 생각하면 될거같아.
🙋♂️ 다른 블록체인이 나누지 않는 이유는 뭔지?
🤖 ...
async function test() {
// 보내는 사람의 키링 생성 후 지갑에 넣어줌.
const sender = caver.wallet.keyring.createFromPrivateKey('0x{private key}')
caver.wallet.add(sender)
// Fee Delegation 할 트랜젝션 생성
const feeDelegatedTx = caver.transaction.feeDelegatedValueTransfer.create({
from: sender.address,
to: '0x176ff0344de49c04be577a3512b6991507647f72',
value: 5,
gas: 50000,
})
// 해당 트랜젝션에 서명
await caver.wallet.sign(sender.address, feeDelegatedTx)
// 서명된 트랜젝션에서 RLP 문자열 가져올 수 있음.
const rlpEncoded = feeDelegatedTx.getRLPEncoding()
// 수수료 납부자 키 만들기
const feePayer = caver.wallet.keyring.createFromPrivateKey('0x{private key}')
// 월렛에 추가.
caver.wallet.add(feePayer)
// Sender 서명한 TX 생성
const feeDelegateTxFromRLPEncoding = caver.transaction.feeDelegatedValueTransfer.create(rlpEncoded)
// 거기에 Fee payer의 서명 추가해줌.
feeDelegateTxFromRLPEncoding.feePayer = feePayer.address
await caver.wallet.signAsFeePayer(feePayer.address, feeDelegateTxFromRLPEncoding)
// 비로소 해당 트랜잭션을 클레이튼 네트워크에 전송할 수 있음.
const receipt = await caver.rpc.klay.sendRawTransaction(rlpEncoded)
console.log(receipt)
}
🙋♂️ 계정 업데이트는 뭘 의미하는가?
🤖 계정의 개인키를 변경하는 것을 의미합니다. + 타입의 변경??
🙋♂️ 보안때문에?? 왜??
🤖 ⚠️ 아마도 보안 문제가 클거같음.
🙋♂️ 그냥 바꾸면 되는거 아니야?
🤖 트랜잭션을 검증할때 공개키가 사용되는데, 공개키와 개인키는 쌍이라서 공개키를 변경 후 개인키를 바꿔야함.
🙋♂️ 자세하게 어떻게 진행되는데?
🤖 원하는 타입의 키링 생성 -> 키링에서 계정 인스턴스 생성-> 인스턴스를 클레이튼에 전송 -> 키링 교체
async function testFunction() {
let sender = caver.wallet.keyring.createFromPrivateKey('0x{private key}')
caver.wallet.add(sender)
// 월렛에서 새로운 개인키 생성. ( 만들 키 갯수 ) default = 1
const newPrivateKey = caver.wallet.keyring.generateSingleKey()
console.log(`new private key string: ${newPrivateKey}`)
// 계정 주소 + 개인키로 새로운 키링 생성.
const newKeyring = caver.wallet.keyring.createWithSingleKey(sender.address, newPrivateKey)
// Account instance 생성
const account = newKeyring.toAccount()
// 인스턴스 클레이튼에 전송. ( tx 생성 -> 사인 -> 전송 )
const updateTx = caver.transaction.accountUpdate.create({
from: sender.address,
account: account,
gas: 50000,
})
await caver.wallet.sign(sender.address, updateTx)
const receipt = await caver.rpc.klay.sendRawTransaction(updateTx)
console.log(receipt)
// 월렛의 키링 업데이트.
sender = caver.wallet.updateKeyring(newKeyring)
}
caver은 저수준의 ABI가 주어지면 모든 메소드를 자동으로 JS 호출로 변환하는 기능이있습니다.
🙋♂️ 이 기능이 왜 필요합니까?
🤖 스마트 컨트랙트는 솔리디티로 작성되는데 이를 친근한 JS 호출로 변환합니다.
const deployedInstance = await contractInstance.deploy({
from: deployer.address,
feeDelegation: true,
feePayer: feePayer.address,
gas: 1500000,
}, byteCode)
3-3. sender(deployer)과 대납자의 서명을 따로 하고 배포할때,
const contractInstance = caver.contract.create(abi)
// deployer 서명?
const signed = await contractInstance.sign({
from: deployer.address,
feeDelegation: true,
gas: 1500000,
}, 'constructor', byteCode)
// 대납자 서명.
await caver.wallet.signAsFeePayer(feePayer.address, signed)
// 클레이튼에 tx 전송
const receipt = await caver.rpc.klay.sendRawTransaction(signed)
// 배포 결과 가져오기.
const deployed = caver.contract.create(abi, receipt.contractAddress)