Multi-signature wallet concept in Blockchain / Solidity - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When using a multi-signature wallet, multiple approvals are needed to complete a transaction.
We want to understand how the time to approve grows as more owners are added.
Analyze the time complexity of the following code snippet.
function executeTransaction(transaction, signatures) {
let validCount = 0;
for (let i = 0; i < owners.length; i++) {
if (signatures.includes(owners[i])) {
validCount++;
}
}
if (validCount >= requiredSignatures) {
process(transaction);
}
}
This code checks how many owners have signed a transaction before executing it.
- Primary operation: Loop through all owners to check signatures.
- How many times: Once for each owner in the wallet.
As the number of owners grows, the code checks more signatures one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 checks |
| 100 | 100 checks |
| 1000 | 1000 checks |
Pattern observation: The number of checks grows directly with the number of owners.
Time Complexity: O(n * m)
This means the time to verify signatures grows linearly with the number of owners and the number of signatures.
[X] Wrong: "Adding more owners won't affect the time because signatures are checked all at once."
[OK] Correct: Each owner must be checked one by one, so more owners mean more checks and more time.
Understanding how loops grow with input size helps you explain how blockchain wallets handle multiple approvals efficiently.
"What if the signatures were stored in a fast lookup structure like a set? How would the time complexity change?"
Practice
multi-signature wallet in blockchain?Solution
Step 1: Understand the multi-signature wallet concept
A multi-signature wallet requires more than one person to approve a transaction before it can be executed.Step 2: Identify the main purpose
This setup protects funds by preventing a single user from spending money alone, increasing security.Final Answer:
To require multiple approvals before spending funds -> Option AQuick Check:
Multi-signature = multiple approvals [OK]
- Thinking it speeds up transactions
- Believing one user controls all funds
- Confusing it with single-key wallets
Solution
Step 1: Identify correct data type for threshold
The threshold is a number representing how many signatures are needed, so an unsigned integer likeuint8is appropriate.Step 2: Check syntax correctness
Assigning a number directly touint8is correct. Using quotes or wrong types causes errors.Final Answer:
uint8 threshold = 1; -> Option DQuick Check:
Threshold is a number, use uint8 [OK]
- Using quotes around numbers
- Assigning string type to threshold
- Using boolean type for threshold
isApproved after calling approveTransaction(1, msg.sender) if the threshold is 2 and only one approval is made?mapping(uint => mapping(address => bool)) approvals;
uint8 threshold = 2;
function approveTransaction(uint txId, address approver) public {
approvals[txId][approver] = true;
}
function isApproved(uint txId) public view returns (bool) {
uint count = 0;
for (uint i = 0; i < owners.length; i++) {
if (approvals[txId][owners[i]]) {
count++;
}
}
return count >= threshold;
}Solution
Step 1: Understand approval counting logic
The function counts how many owners approved the transaction and compares it to the threshold.Step 2: Analyze given scenario
Only one approval is made but threshold is 2, socountis 1 which is less than 2.Final Answer:
false -> Option BQuick Check:
Approvals < threshold = false [OK]
- Assuming one approval is enough
- Ignoring threshold comparison
- Confusing approval mapping structure
function approveTransaction(uint txId) public {
approvals[txId][msg.sender] = true;
if (isApproved(txId)) {
executeTransaction(txId);
}
}
function isApproved(uint txId) public view returns (bool) {
uint count = 0;
for (uint i = 0; i <= owners.length; i++) {
if (approvals[txId][owners[i]]) {
count++;
}
}
return count >= threshold;
}Solution
Step 1: Check the for loop boundary
The loop usesi <= owners.length, which causes out-of-bounds access because array indices go from 0 to length-1.Step 2: Correct the loop condition
Changing toi < owners.lengthprevents accessing invalid index and runtime errors.Final Answer:
Loop condition should be < instead of <= -> Option CQuick Check:
Array index out of bounds fixed by < [OK]
- Using <= in loops causing errors
- Ignoring array index limits
- Thinking event emission fixes logic bugs
mapping(uint => mapping(address => bool)) approvals;
address[5] owners;
uint8 threshold = 3;
function executeTransaction(uint txId) public {
uint count = 0;
for (uint i = 0; i < owners.length; i++) {
if (approvals[txId][owners[i]]) {
count++;
}
}
if (count >= threshold) {
// execute the transaction
} else {
revert("Not enough approvals");
}
}Solution
Step 1: Analyze the approval counting logic
The code counts how many owners approved the transaction by checking theapprovalsmapping for each owner.Step 2: Check threshold enforcement
If the count is at least the threshold (3), the transaction executes; otherwise, it reverts with an error.Final Answer:
This code correctly enforces the 3-of-5 approval rule -> Option AQuick Check:
Count approvals >= threshold = enforce rule [OK]
- Setting threshold incorrectly
- Looping over wrong data structure
- Using return instead of revert for errors
