In most of the blockchain implementation, only sender is required to sign the transaction. With the sender's signature, we would trust that the operation is authorized by the sender. Transactions like Transfer is typical example that sender would send some tokens / assets to the receiver (without receiver's permission). In real world, a vast use cases require authorization among all parties in the transaction. For example, Alice would give Bob 20 ABT to get a conference ticket Bob owned. In this transaction, Alice is actually requesting an exchange between her 20 ABTs and Bob's ticket. Bob must authorize this operation to make the transaction valid. So this is the basic use case for Multisig.
In Forge, transaction protocols can decide if they'd enable multisig or not. If multisig is enabled, then the involved parties must sign the tx in order, with the multisig structure:
message Multisig {
// signer address
string signer = 1;
// public key for signer
bytes pk = 2;
// signature
bytes signature = 3;
// extra data
google.protobuf.Any data = 15;
}
Multisig is used in transaction structure:
message Transaction {
string from = 1;
uint64 nonce = 2;
// use DID for the chain. "did:" prefix is omitted
string chain_id = 3;
// public key of the sender
bytes pk = 4;
// signature of the transaction
bytes signature = 13;
// we will support multiple signatures in case of certain tx need multiple
// parties' signature.
repeated Multisig signatures = 14;
google.protobuf.Any itx = 15;
}
Normally data
is not required in Multisig. A signer need to fill in signer
address, signer pk
, and attach the signature in the beginning of the signatures
array in transaction data structure. Then sign the whole transaction, and then add the generated signature into the signature
of this multisig.
Let's use Exchange transaction to illustrate the above example:
Since Alice initiated the transaction, she's sender, Bob's receiver. The sender will always add the signature into signature
field, and the receiver (or more parties) will do the multisig thereafter.
Step 1: Alice crate an Exchange ITX
Alice will fill in an Exchange itx:
%ForgeAbi.ExchangeTx{
receiver: %ForgeAbi.ExchangeInfo{
assets: ["zjdzwEM42m3GT5nLRPvwGzmLCv8EofxMfy4e"],
value: nil
},
sender: %ForgeAbi.ExchangeInfo{
assets: [],
value: %ForgeAbi.BigUint{value: <<2, 198, 138, 240, 187, 20, 0, 0>>}
},
to: "z11PsZYbZWBqBDB3WPhCCu2r6G4zuxrLRsFy"
}
And then put it into a transaction with signature (you need to encode this itx to a Google.Protobuf.Any with type_url fg:t:exchange
):
%ForgeAbi.Transaction{
chain_id: "forge",
from: "z11CSMrHjLnk4QFtFp9zNhKJe2vNBDeFB5cR",
itx: %Google.Protobuf.Any{
type_url: "fg:t:exchange",
value: <<10, 36, 122, 49, 49, 80, 115, 90, 89, 98, 90, 87, 66, 113, 66, 68,
66, 51, 87, 80, 104, 67, 67, 117, 50, 114, 54, 71, 52, 122, 117, 120, 114,
76, 82, 115, 70, 121, 18, 12, 10, 10, 10, 8, 2, ...>>
},
nonce: 124,
pk: <<245, 235, 0, 135, 189, 169, 233, 188, 28, 12, 204, 254, 237, 11, 99,
159, 185, 150, 174, 128, 110, 183, 127, 115, 21, 195, 18, 37, 176, 134, 165,
71>>,
signature: <<23, 89, 219, 32, 220, 205, 80, 109, 105, 90, 98, 0, 39, 118, 89,
246, 87, 167, 247, 201, 241, 217, 224, 19, 217, 210, 211, 206, 116, 216,
159, 122, 147, 67, 44, 135, 61, 253, 88, 234, 145, 222, 119, 236, ...>>,
signatures: []
}
Then deliver this tx to Bob with any off-chain approach. E.g. send by email or send a message with ABT wallet. Once Bob get this tx he can generate a Multisig as described above and attached to the tx:
%ForgeAbi.Transaction{
chain_id: "forge",
from: "z11CSMrHjLnk4QFtFp9zNhKJe2vNBDeFB5cR",
itx: %Google.Protobuf.Any{
type_url: "fg:t:exchange",
value: <<10, 36, 122, 49, 49, 80, 115, 90, 89, 98, 90, 87, 66, 113, 66, 68,
66, 51, 87, 80, 104, 67, 67, 117, 50, 114, 54, 71, 52, 122, 117, 120, 114,
76, 82, 115, 70, 121, 18, 12, 10, 10, 10, 8, 2, ...>>
},
nonce: 124,
pk: <<245, 235, 0, 135, 189, 169, 233, 188, 28, 12, 204, 254, 237, 11, 99,
159, 185, 150, 174, 128, 110, 183, 127, 115, 21, 195, 18, 37, 176, 134, 165,
71>>,
signature: <<23, 89, 219, 32, 220, 205, 80, 109, 105, 90, 98, 0, 39, 118, 89,
246, 87, 167, 247, 201, 241, 217, 224, 19, 217, 210, 211, 206, 116, 216,
159, 122, 147, 67, 44, 135, 61, 253, 88, 234, 145, 222, 119, 236, ...>>,
signatures: [
%ForgeAbi.Multisig{
data: nil,
pk: <<245, 235, 0, 135, 189, 169, 233, 188, 28, 12, 204, 254, 237, 11, 99,
159, 185, 150, 174, 128, 110, 183, 127, 115, 21, 195, 18, 37, 176, 134,
165, 71>>,
signature: <<207, 191, 238, 169, 227, 110, 34, 218, 191, 63, 143, 190,
236, 76, 145, 239, 143, 35, 212, 217, 7, 116, 198, 12, 58, 63, 102, 173,
241, 154, 81, 128, 185, 144, 42, 67, 69, 187, 202, ...>>,
signer: "z11CSMrHjLnk4QFtFp9zNhKJe2vNBDeFB5cR"
}
]
}
Then Bob can deliver this tx to the chain. And since both parties signed the tx, it will be executed.