Invoking a multisig transaction

Introduction

여러 서명이 필요한 트랜잭션이 만들어지고 Klaytn에 보내지는 과정은 하나의 서명이 필요한 트랜잭션이 생성, 전송되는 과정과 비슷합니다. 한 가지 차이는, 단일 서명 트랜잭션은 1회 서명으로 트랜잭션이 전송되는 반면, 다중 서명 트랜잭션은 가중치의 합이 임계치 이상이 될 때까지 다른 서명자가 계속해서 추가로 서명해야 트랜잭션을 전송할 수 있다는 점입니다.

따라서 다중 서명 트랜잭션은 크게 두 단계로 구성됩니다. 첫번째는 트랜잭션을 생성 및 전송 요청하는 단계이며, 두번째는 트랜잭션에 여러 서명자가 서명하는 단계입니다.

트랜잭션 생성 단계에서는 단일 서명 트랜잭션 생성 및 전송 요청과 동일한 API를 사용합니다. 계정을 조회했을 때 이 계정이 다중 서명을 가지는 계정이라면 트랜잭션을 전송하지 않고 트랜잭션 관리시스템내에 트랜잭션을 풀링한 다음 트랜잭션을 리턴합니다. 이 때, 트랜잭션이 실제로 전송되지는 않고 tx_hash 가 반환되며 해당 값은 풀링된 트랜잭션의 식별자로 사용된다.

트랜잭션에 여러 서명자가 서명하는 단계에서는 계정에 있는 여러 개인키의 각 사용자가 앞에서 얻은 tx_hash에 서명합니다. 트랜잭션 관리시스템은 서명 가중치 합이 임계치 이상일 때에만 트랜잭션을 네트워크에 전송합니다.

Invoking a multisig transaction

API call flow

1. Create a new account

POST /v2/account
  • Request Headers

    Name

    Description

    Required

    Type

    authorization

    KAS authentication token

    Yes

    string

    x-krn

    KAS resource name

    Yes

    string

  • Example

    • Command

    curl -i -X POST -u {your_accessKeyId}:{your_secretAccessKey} -H 'X-Krn: krn:1001:wallet:GC1:account:rp1' -H 'Content-Type: application/json' --max-time 30 --globoff 'https://wallet-api.beta.klaytn.io/v2/account'
    • Request

    // POST /v2/account
    // X-Krn: krn:1001:wallet:GC1:account:rp1
    // Content-Type: application/json
    • Response

      200 - OK

      Name

      Type

      code

      number

      result

      object

      result.address

      string

      result.chain_id

      number

      result.created_at

      number

      result.key_id

      string

      result.krn

      string

      result.public_key

      string

      result.updated_at

      number

    // HTTP/1.1 200 OK
    // content-type: application/json; charset=utf-8
    // date: Thu, 18 Jun 2020 22:10:37 GMT
    // content-length: 439
    // x-envoy-upstream-service-time: 342
    // server: istio-envoy
    {
    "code": 0,
    "result": {
    "address": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e",
    "chain_id": 1001,
    "created_at": 1592518237,
    "key_id": "krn:1001:wallet:GC1:account:rp1:0x1631e7224a764d51a91054346d5e35368dccff3929545f0e2ee9faa15d4521bb",
    "krn": "krn:1001:wallet:GC1:account:rp1",
    "public_key": "0x04a74c5b41b077019bcbca7f3ae32658fe16cfb9aaed82314cd052337e24aaca8143dafd52335f4e5895fc1275dadf3a09f44a6fa59d35d4052a9a8b10b91f88ab",
    "updated_at": 1592518237
    }
    }

2. Send balances to the account to pay the fee for the account update transaction

POST /v2/tx/value
{
"from":"${from}",
"value": "${value}",
"to":"${to}",
"memo":"${memo}",
"nonce": ${nonce},
"gas_limit": ${gas_limit},
"submit": ${submit}
}
  • Request Headers

    Name

    Description

    Required

    Type

    authorization

    KAS authentication token

    Yes

    string

    x-krn

    KAS resource name

    Yes

    string

  • Body Parameters

    Name

    Description

    Required

    Type

    from

    Sender's address

    Yes

    string

    value

    transfer amount

    Yes

    string

    to

    Receiver's address

    Yes

    string

    memo

    Value transfer memo message

    No

    string

    nonce

    Nonce

    No

    number

    gas_limit

    Gas limit

    No

    number

    submit

    Submit transaction

    No

    string

  • Example

    • Command

    curl -i -X POST -u {your_accessKeyId}:{your_secretAccessKey} -H 'X-Krn: krn:1001:wallet:GC1:account:rp1' -H 'Content-Type: application/json' --max-time 30 --globoff 'https://wallet-api.beta.klaytn.io/v2/tx/value' -d '{ "from":"0xf4584afef226e41b384e11b94a9e2f635366dc97", "value": "0x91100000000000", "to":"0xA04c1e919A24F330023BB594f6E156883bd5dA6e", "memo":"with memo", "nonce": 0, "gas_limit": 1000000, "submit": true }'
    • Request

    // POST /v2/tx/value
    // X-Krn: krn:1001:wallet:GC1:account:rp1
    // Content-Type: application/json
    {
    "from": "0xf4584afef226e41b384e11b94a9e2f635366dc97",
    "value": "0x91100000000000",
    "to": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e",
    "memo": "with memo",
    "nonce": 0,
    "gas_limit": 1000000,
    "submit": true
    }
    • Response

      200 - OK

      Name

      Type

      code

      number

      result

      object

      result.from

      string

      result.gas_limit

      number

      result.gas_price

      string

      result.input

      string

      result.nonce

      number

      result.rlp

      string

      result.signatures

      array

      result.status

      string

      result.to

      string

      result.transaction_hash

      string

      result.type_int

      number

      result.value

      string

    // HTTP/1.1 200 OK
    // content-type: application/json; charset=utf-8
    // date: Thu, 18 Jun 2020 22:11:38 GMT
    // content-length: 842
    // x-envoy-upstream-service-time: 61
    // server: istio-envoy
    {
    "code": 0,
    "result": {
    "from": "0xf4584afef226e41b384e11b94a9e2f635366dc97",
    "gas_limit": 1000000,
    "gas_price": "0x5d21dba00",
    "input": "0x77697468206d656d6f",
    "nonce": 71,
    "rlp": "0x10f890478505d21dba00830f424094a04c1e919a24f330023bb594f6e156883bd5da6e879110000000000094f4584afef226e41b384e11b94a9e2f635366dc978977697468206d656d6ff847f8458207f5a0a3788893e23388e98a389dbe32228bc7937ba45592dee5e4c4b786f6523b1598a06bec46127907d410023f6e738d76caff04950c994999ec1d9659d9d6ef5205d8",
    "signatures": [
    {
    "R": "0xa3788893e23388e98a389dbe32228bc7937ba45592dee5e4c4b786f6523b1598",
    "S": "0x6bec46127907d410023f6e738d76caff04950c994999ec1d9659d9d6ef5205d8",
    "V": "0x7f5"
    }
    ],
    "status": "Submitted",
    "to": "0xa04c1e919a24f330023bb594f6e156883bd5da6e",
    "transaction_hash": "0xebcf2b3a23e935febc64eab6cc0105d9863f37cde63f3cb49b7c4a99310fbde6",
    "type_int": 16,
    "value": "0x91100000000000"
    }
    }

3. Create the second account which will be associated with the multisig account

POST /v2/account
  • Request Headers

    Name

    Description

    Required

    Type

    authorization

    KAS authentication token

    Yes

    string

    x-krn

    KAS resource name

    Yes

    string

  • Example

    • Command

    curl -i -X POST -u {your_accessKeyId}:{your_secretAccessKey} -H 'X-Krn: krn:1001:wallet:GC1:account:rp1' -H 'Content-Type: application/json' --max-time 30 --globoff 'https://wallet-api.beta.klaytn.io/v2/account'
    • Request

    // POST /v2/account
    // X-Krn: krn:1001:wallet:GC1:account:rp1
    // Content-Type: application/json
    • Response

      200 - OK

      Name

      Type

      code

      number

      result

      object

      result.address

      string

      result.chain_id

      number

      result.created_at

      number

      result.key_id

      string

      result.krn

      string

      result.public_key

      string

      result.updated_at

      number

    // HTTP/1.1 200 OK
    // content-type: application/json; charset=utf-8
    // date: Thu, 18 Jun 2020 22:11:48 GMT
    // content-length: 439
    // x-envoy-upstream-service-time: 202
    // server: istio-envoy
    {
    "code": 0,
    "result": {
    "address": "0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "chain_id": 1001,
    "created_at": 1592518309,
    "key_id": "krn:1001:wallet:GC1:account:rp1:0x317aefe8e62bbf5c2cb93dc859ecd0cc2559248b50244857f5e19e8adbe74ad6",
    "krn": "krn:1001:wallet:GC1:account:rp1",
    "public_key": "0x04fb54699c8134f4f3ae339ad672f2ffbe3403c09032fb3668db34da0b9625e406bdcbb3f94887e28f4236a72a3abf89f221ad8ee320a921fb93a61423e99459eb",
    "updated_at": 1592518309
    }
    }

4. Update the first account to have multiple private keys with weights and a threshold for multisig

PUT /v2/account/multisig
{
"address": "${address}",
"threshold": ${threshold},
"weighted_keys": [
{
"weight": 3,
"public_key": "${pubkey}"
},
{
"weight": 3,
"public_key": "${msig_pubkey1}"
}
]
}
  • Request Headers

    Name

    Description

    Required

    Type

    authorization

    KAS authentication token

    Yes

    string

    x-krn

    KAS resource name

    Yes

    string

  • Body Parameters

    Name

    Description

    Required

    Type

    address

    Account address

    Yes

    string

    threshold

    Threshold

    Yes

    number

    pubkey

    public key

    Yes

    string

    msig_pubkey1

    Public key 1 for multisig update

    Yes

    string

  • Example

    • Command

    curl -i -X PUT -u {your_accessKeyId}:{your_secretAccessKey} -H 'X-Krn: krn:1001:wallet:GC1:account:rp1' -H 'Content-Type: application/json' --max-time 30 --globoff 'https://wallet-api.beta.klaytn.io/v2/account/multisig' -d '{ "address": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e", "threshold": 6, "weighted_keys": [ { "weight": 3, "public_key": "0x04a74c5b41b077019bcbca7f3ae32658fe16cfb9aaed82314cd052337e24aaca8143dafd52335f4e5895fc1275dadf3a09f44a6fa59d35d4052a9a8b10b91f88ab" }, { "weight": 3, "public_key": "0x04fb54699c8134f4f3ae339ad672f2ffbe3403c09032fb3668db34da0b9625e406bdcbb3f94887e28f4236a72a3abf89f221ad8ee320a921fb93a61423e99459eb" } ] }'
    • Request

    // PUT /v2/account/multisig
    // X-Krn: krn:1001:wallet:GC1:account:rp1
    // Content-Type: application/json
    {
    "address": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e",
    "threshold": 6,
    "weighted_keys": [
    {
    "weight": 3,
    "public_key": "0x04a74c5b41b077019bcbca7f3ae32658fe16cfb9aaed82314cd052337e24aaca8143dafd52335f4e5895fc1275dadf3a09f44a6fa59d35d4052a9a8b10b91f88ab"
    },
    {
    "weight": 3,
    "public_key": "0x04fb54699c8134f4f3ae339ad672f2ffbe3403c09032fb3668db34da0b9625e406bdcbb3f94887e28f4236a72a3abf89f221ad8ee320a921fb93a61423e99459eb"
    }
    ]
    }
    • Response

      200 - OK

      Name

      Type

      code

      number

      result

      object

      result.address

      string

      result.krn

      string

      result.multi_sig_keys

      array

      result.threshold

      number

      result.transaction_hash

      string

      result.updated_at

      number

    // HTTP/1.1 200 OK
    // content-type: application/json; charset=utf-8
    // date: Thu, 18 Jun 2020 22:12:38 GMT
    // content-length: 584
    // x-envoy-upstream-service-time: 92
    // server: istio-envoy
    {
    "code": 0,
    "result": {
    "address": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e",
    "krn": "krn:1001:wallet:GC1:account:rp1",
    "multi_sig_keys": [
    {
    "public_key": "0x04a74c5b41b077019bcbca7f3ae32658fe16cfb9aaed82314cd052337e24aaca8143dafd52335f4e5895fc1275dadf3a09f44a6fa59d35d4052a9a8b10b91f88ab",
    "weight": 3
    },
    {
    "public_key": "0x04fb54699c8134f4f3ae339ad672f2ffbe3403c09032fb3668db34da0b9625e406bdcbb3f94887e28f4236a72a3abf89f221ad8ee320a921fb93a61423e99459eb",
    "weight": 3
    }
    ],
    "threshold": 6,
    "transaction_hash": "0x311ccc81b0dbec168b123d14318fc59addf07226a6e0c1e2257dedbfedc655c6",
    "updated_at": 1592518358
    }
    }

5. Invoke a value transaction from the first account (the updated account)

POST /v2/tx/value
{
"from":"${from}",
"value": "${value}",
"to":"${to}",
"memo":"${memo}",
"nonce": ${nonce},
"gas_limit": ${gas_limit},
"submit": ${submit}
}
  • Request Headers

    Name

    Description

    Required

    Type

    authorization

    KAS authentication token

    Yes

    string

    x-krn

    KAS resource name

    Yes

    string

  • Body Parameters

    Name

    Description

    Required

    Type

    from

    Sender's address

    Yes

    string

    value

    transfer amount

    Yes

    string

    to

    Receiver's address

    Yes

    string

    memo

    Value transfer memo message

    No

    string

    nonce

    Nonce

    No

    number

    gas_limit

    Gas limit

    No

    number

    submit

    Submit transaction

    No

    string

  • Example

    • Command

    curl -i -X POST -u {your_accessKeyId}:{your_secretAccessKey} -H 'X-Krn: krn:1001:wallet:GC1:account:rp1' -H 'Content-Type: application/json' --max-time 30 --globoff 'https://wallet-api.beta.klaytn.io/v2/tx/value' -d '{ "from":"0xA04c1e919A24F330023BB594f6E156883bd5dA6e", "value": "0x1233", "to":"0x275CaDFc171d26d607682746BdbFa910f435Cd7C", "memo":"with memo", "nonce": 0, "gas_limit": 1000000, "submit": true }'
    • Request

    // POST /v2/tx/value
    // X-Krn: krn:1001:wallet:GC1:account:rp1
    // Content-Type: application/json
    {
    "from": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e",
    "value": "0x1233",
    "to": "0x275CaDFc171d26d607682746BdbFa910f435Cd7C",
    "memo": "with memo",
    "nonce": 0,
    "gas_limit": 1000000,
    "submit": true
    }
    • Response

      200 - OK

      Name

      Type

      code

      number

      result

      object

      result.from

      string

      result.gas_limit

      number

      result.gas_price

      string

      result.input

      string

      result.nonce

      number

      result.status

      string

      result.to

      string

      result.transaction_id

      string

      result.type_int

      number

      result.value

      string

    // HTTP/1.1 200 OK
    // content-type: application/json; charset=utf-8
    // date: Fri, 19 Jun 2020 02:09:23 GMT
    // content-length: 347
    // x-envoy-upstream-service-time: 34
    // server: istio-envoy
    {
    "code": 0,
    "result": {
    "from": "0xa04c1e919a24f330023bb594f6e156883bd5da6e",
    "gas_limit": 1000000,
    "gas_price": "0x5d21dba00",
    "input": "0x77697468206d656d6f",
    "nonce": 1,
    "status": "Pending",
    "to": "0x275cadfc171d26d607682746bdbfa910f435cd7c",
    "transaction_id": "0x703c9f1fb079b413e37b997be431b51579865e3d34cd7212ca7b3894d98572d5",
    "type_int": 16,
    "value": "0x1233"
    }
    }

6. Retrieving the transaction that requires the other signatures to fulfill the threshold.

GET /v2/multisig/tx
{
"address":"${address}",
"limit": ${limit},
"bookmark":"${bookmark}"
}
  • Request Headers

    Name

    Description

    Required

    Type

    authorization

    KAS authentication token

    Yes

    string

    x-krn

    KAS resource name

    Yes

    string

  • Body Parameters

    Name

    Description

    Required

    Type

    address

    Account address

    Yes

    string

    limit

    Page size

    Yes

    number

    bookmark

    Bookmark for database search

    Yes

    string

  • Example

    • Command

    curl -i -X GET -u {your_accessKeyId}:{your_secretAccessKey} -H 'X-Krn: krn:1001:wallet:GC1:account:rp1' -H 'Content-Type: application/json' --max-time 30 --globoff 'https://wallet-api.beta.klaytn.io/v2/multisig/tx' -d '{ "address":"0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2", "limit": 10, "bookmark":"" }'
    • Request

    // GET /v2/multisig/tx
    // X-Krn: krn:1001:wallet:GC1:account:rp1
    // Content-Type: application/json
    {
    "address": "0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "limit": 10,
    "bookmark": ""
    }
    • Response

      200 - OK

      Name

      Type

      code

      number

      result

      object

      result.bookmark

      string

      result.count

      number

      result.transactions

      array

    // HTTP/1.1 200 OK
    // content-type: application/json; charset=utf-8
    // date: Fri, 19 Jun 2020 02:09:56 GMT
    // content-length: 1541
    // x-envoy-upstream-service-time: 5
    // server: istio-envoy
    {
    "code": 0,
    "result": {
    "bookmark": "0x703c9f1fb079b413e37b997be431b51579865e3d34cd7212ca7b3894d98572d5##TX_0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "count": 2,
    "transactions": [
    {
    "account": "0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "chain_id": 1001,
    "created_at": 1592518387,
    "multi_sig_keys": [
    {
    "address": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e",
    "weight": 3
    },
    {
    "address": "0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "weight": 3
    }
    ],
    "status": 2,
    "threshold": 6,
    "transaction_data": {
    "from": "0xa04c1e919a24f330023bb594f6e156883bd5da6e",
    "gas_limit": 1000000,
    "gas_price": "0x5d21dba00",
    "input": "0x77697468206d656d6f",
    "nonce": 0,
    "to": "0x275cadfc171d26d607682746bdbfa910f435cd7c",
    "type_int": 16,
    "value": "0x123"
    },
    "transaction_id": "0xd90d082bc209587f6991ee043ac344914ea786d0581c7110ee01d57b9624f696",
    "type": "TX_0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "updated_at": 1592518387
    },
    {
    "account": "0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "chain_id": 1001,
    "created_at": 1592532563,
    "multi_sig_keys": [
    {
    "address": "0xA04c1e919A24F330023BB594f6E156883bd5dA6e",
    "weight": 3
    },
    {
    "address": "0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "weight": 3
    }
    ],
    "status": 2,
    "threshold": 6,
    "transaction_data": {
    "from": "0xa04c1e919a24f330023bb594f6e156883bd5da6e",
    "gas_limit": 1000000,
    "gas_price": "0x5d21dba00",
    "input": "0x77697468206d656d6f",
    "nonce": 0,
    "to": "0x275cadfc171d26d607682746bdbfa910f435cd7c",
    "type_int": 16,
    "value": "0x1233"
    },
    "transaction_id": "0x703c9f1fb079b413e37b997be431b51579865e3d34cd7212ca7b3894d98572d5",
    "type": "TX_0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "updated_at": 1592532563
    }
    ]
    }
    }

7. Sign the retrieved transaction with private key to fulfill the threshold.

POST /v2/multisig/tx/sign
{
"address":"${address}",
"transaction_id":"${transaction_id}"
}
  • Request Headers

    Name

    Description

    Required

    Type

    authorization

    KAS authentication token

    Yes

    string

    x-krn

    KAS resource name

    Yes

    string

  • Body Parameters

    Name

    Description

    Required

    Type

    address

    Account address

    Yes

    string

    transaction_id

    multisig pending transaction ID

    Yes

    string

  • Example

    • Command

    curl -i -X POST -u {your_accessKeyId}:{your_secretAccessKey} -H 'X-Krn: krn:1001:wallet:GC1:account:rp1' -H 'Content-Type: application/json' --max-time 30 --globoff 'https://wallet-api.beta.klaytn.io/v2/multisig/tx/sign' -d '{ "address":"0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2", "transaction_id":"0x703c9f1fb079b413e37b997be431b51579865e3d34cd7212ca7b3894d98572d5" }'
    • Request

    // POST /v2/multisig/tx/sign
    // X-Krn: krn:1001:wallet:GC1:account:rp1
    // Content-Type: application/json
    {
    "address": "0x8Df1dE9761e17cf9F6013A445a8874e0Efee77f2",
    "transaction_id": "0x703c9f1fb079b413e37b997be431b51579865e3d34cd7212ca7b3894d98572d5"
    }
    • Response

      200 - OK

      Name

      Type

      code

      number

      result

      object

      result.signed_weight

      number

      result.status

      string

      result.threshold

      number

      result.transaction_hash

      string

      result.transaction_id

      string

      result.weight

      number

    // HTTP/1.1 200 OK
    // content-type: application/json; charset=utf-8
    // date: Fri, 19 Jun 2020 02:10:42 GMT
    // content-length: 260
    // x-envoy-upstream-service-time: 140
    // server: istio-envoy
    {
    "code": 0,
    "result": {
    "signed_weight": 6,
    "status": "Submitted",
    "threshold": 6,
    "transaction_hash": "0xb9c19e49b8d86af3dbdcfa0591378d72e74e078bc930a5f97c0e8b1cddfbe67e",
    "transaction_id": "0x703c9f1fb079b413e37b997be431b51579865e3d34cd7212ca7b3894d98572d5",
    "weight": 3
    }
    }