Caver-js에 대한 얕은 지식.

J-USER·2022년 5월 6일
0

Klaytn

목록 보기
1/1
post-thumbnail

계정

계정키

계정과 연결된 키 구조.

  1. AccountKeyNil : 공백 키를 나타냄.

  2. AccountKeyLegacy : 키 쌍에서 파생된 주소를 가진 계정에 사용.

    키쌍에서 파생된지 어케아냐?

    • 공개키를 ecrecover(txhash, txsig)로 얻기.
    • 주소는 발신자입니다..???
  3. AccountKeyPublic : 하나의 공개 키를 가진 계정에 사용

    ecrecover(txhash, txsig) === 공개키?? 로 판별.

  4. AccountKeyFail : 트랜잭션 유효성 검증 프로세스는 항상 실패하게 됨.

  5. AccountKeyWeightedMultiSig : threshold + WeightedPublicKeys( 공개키 + 가중치 + 리스트 )

    threshold : 서명시 공개키의 가중치보다 작아야함.
    서명된 공개키 < WeightedPublicKey 여야함.

  6. AccountKeyRoleBased : 역할마다 엑세스 범위를 나눈 역할 기반 키.

    RoleTransaction : TxTypeAccountUpdate 이외
    RoleAccountUpdate : TxTypeAccountUpdate 만
    RoleFeePayer : FeePayer 트랙잭션시

트랜잭션

구성요소

🙋‍♂️ 발신자가 동일한 논스를 가진 두 개의 트랜잭션을 생성하면 하나만 실행된다...? 논스를 설정할 수 있다고??

클레이튼에서의 트랜잭션 서명

기존 : 공개키 <-> 서명 (서로 파생)
클레이튼 : 공개키(키쌍) // 서명 => 서명에서 주체의 주소를 가져올 수 없음 => from(계정키)이 있는 이유.

SenderTxHash

트랜잭션 수수료 납부자의 주소와 서명이 없는 트랜잭션의 해시

🙋‍♂️ 서명없이 해시를 어케 만드냐?
🤖 납부자가 동의하는 서명을 하면 해시 생성됨.
🤖 약간 착불같은 느낌

SenderTxHash를 얻기 위한 방법은 트랜잭션 유형에 따라 다름

트랜잭션 유형 종류

앞에 (TxType)은 생략하겠음..(너무길어)
1. LegacyTransaction : 이전에 Klaytn에 존재했던 트랜잭션 유형

  1. ValueTransfer : 사용자가 KLAY를 전송할 때 사용하는 유형
  2. ValueTransferMemo : 특정 메시지와 함께 KLAY를 보내려고 할 때 사용하는 유형
  3. SmartContractDeploy : 지정된 주소에 스마트 컨트랙트를 배포 할 때 사용하는 유형
  4. SmartContractExecution : to가 스마트 컨트랙트 계정일 때 스마트 컨트랙트를 실행하고, input에 입력된 데이터를 이용.
  5. AccountUpdate : 해당 계정의 키를 업데이트
  6. Cancel : 트랜잭션 풀에서 같은 논스를 가진 트랜잭션을 취소할 때 사용.
  7. ChainDataAnchoring : 서비스체인 데이터를 Klaytn 메인체인에 앵커링하는 트랜잭션 유형.

트랜잭션 비용 위임 종류

  1. FeeDelegatedValueTransfer : 사용자가 KLAY를 보내려고 할 때 사용

  2. FeeDelegatedValueTransferMemo : 메시지와 함께 Klay를 보내려고 할때 사용

  3. FeeDelegatedSmartContractDeploy : 수수료 위임하는 컨트랙트를 배포.

  4. FeeDelegatedSmartContractExecution : to가 스마트 컨트랙트 계정일 때 스마트 컨트랙트를 실행하고, input에 입력된 데이터를 이용. 트랜잭션 수수료는 지정된 수수료 납부자가 지불.

  5. FeeDelegatedAccountUpdate : 해당 계정의 키를 업데이트시 수수료 납부자가 지불.

  6. FeeDelegatedCancel : 같은 논스를 가진 트랜잭션을 취소시 수수료 납부자가 지불.

  7. FeeDelegatedChainDataAnchoring : 앵커링시 수수료를 납부자가 지불.

부분 비용 위임 종류

트랜잭션 비용 위임 종류와 똑같지만 Ratio 기능의 추가로 일부는 납부자가, 일부는 본인이 지불하는 기능.

Caver 예시

Basic: keyring이란?

Klaytn 계정의 주소와 개인 키를 포함하는 구조.

  • SingleKeyring :하나의 주소와 하나의 개인 키를 저장
  • MultipleKeyring : 하나의 주소와 여러 개인 키를 저장
  • RoleBasedKeyring : 각 역할에 대해 하나의 주소와 하나 이상의 개인 키를 저장.

🙋‍♂️ 역할은 어떻게 표현하나요?
🤖 [[roleTransactionKey],[roleAccountUpdateKey],[FeePayerKey]]이런 이차원 배열로 표현.
🙋‍♂️ 역할은 뭐가 있나요?
🤖
🙋‍♂️ 보니까 키링을 월렛에 추가해주는거 같은데 왜 그러나요?
🤖 월렛에 있어야지 그때그때 또 생성하는게 아니라 한번만 만들고 계속 쓰징

키링 생성방법

  • singleKey 생성
  • 개인키로 SingleKeyring 생성
  • 개인키와 계정 주소로 SingleKeyring 생성
  • 여러 개인키로 MultipleKeyring 생성
  • 개인키로 RoleBasedKeyring 생성

Caver을 이용한 몇가지 예시.

예시) 트랜잭션 서명

서명은 wallet을 통해 할 수 있고 트랜잭션을 보낼려면 2가지 단계를 거침.

  1. 서명 (caver.wallet에 키링추가 or transction.sign )

    • 방법 1. 키링 월렛에 추가.
    // 키링 생성
    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)
    • 방법 2. transction.sign() 사용
    // 키링 생성
    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)
  2. RLP 인코딩된 서명된 트랜잭션을 caver.rpc.klay.sendRawTransaction을 통해 Klaytn에 전송

다른 트랜잭션 타입 실행

🙋‍♂️ 다른 트랜잭션 타입 왜 나누는데?
🤖 목적에 따라 최적의 트랜잭션을 제공하면 사용자가 사용하기 좋거든.
🙋‍♂️ 이해가 안가요
🤖 목적에 따라 거래의 유형을 바꾼다는 걸로 생각하면, 작은 금액은 "일시불"로 거래 하고 비싼 금액은 "할부"로 거래 하는걸 생각하면 될거같아.
🙋‍♂️ 다른 블록체인이 나누지 않는 이유는 뭔지?
🤖 ...

예시 ) Fee Delegation 타입 실행

  • 수수료 대납자의 서명이 없는 경우,
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 호출로 변환합니다.

  1. 스마트 컨트랙트인 .sol 파일을 컴파일해서 바이트 코드 , ABI를 얻음.
  2. ABI로 컨트랙트 인스턴스 생성 가능.
    2-1. 배포 되어있지 않다면, 주소를 두번째 인자로 넣어줌.
  3. 배포 하기
    3-1. 스마트 컨트랙트의 바이트 코드를 data 필드에 넣어주면 배포 가능.
    3-2. 배포시 수수료 대납을 위하면,
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)
profile
호기심많은 개발자

0개의 댓글