-
-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MultiSig Implementation #417
Merged
Merged
Changes from 7 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
91ca2fc
Rebase
leonardocustodio 5bc5f13
requested changes
justkawal fdec2b4
multisig preparation
justkawal 3164b62
Merge remote-tracking branch 'origin/main' into justkawal/multisig
justkawal 1757db1
multi sig functionality
justkawal 88f8fb4
refactor
justkawal bc04678
Update tests.yml
justkawal 3260b56
Merge branch 'main' into justkawal/multisig
justkawal 6c4abe5
Merge branch 'main' into justkawal/multisig
justkawal 66067b8
signing test with multisig implementation
justkawal c666ff8
completed multisig implementation
justkawal 821830d
remove multisig from polkadart_keyring
justkawal 2b5eb26
formatting
justkawal ab4e67b
fix errors
justkawal d7ad6e7
important changes
justkawal d2ceff3
formatting and few changes
justkawal 2ce0d64
bug fix
justkawal 3bd59cc
docs improvement
justkawal ab2f601
change docs
justkawal c32f851
improve example
justkawal 312de9f
change keypair in example
justkawal daee509
improve docs and example
justkawal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
part of polkadart_keyring; | ||
|
||
final PREFIX = utf8.encode('modlpy/utilisuba'); | ||
|
||
class MultiSig { | ||
static Uint8List createMultiSigBytes( | ||
List<Uint8List> signatories, int threshold) { | ||
if (signatories.isEmpty) { | ||
throw ArgumentError('No signatories provided.'); | ||
} | ||
|
||
// sort the signatories | ||
final sortedSignatories = List<Uint8List>.from(signatories) | ||
..sort(uint8ListCompare); | ||
|
||
// generate the multi output result | ||
final result = <int>[]; | ||
|
||
// append the PREFIX | ||
result.addAll(PREFIX); | ||
|
||
// append the length | ||
result.addAll( | ||
scale_codec.CompactCodec.codec.encode(sortedSignatories.length)); | ||
for (final who in sortedSignatories) { | ||
result.addAll(who); | ||
} | ||
// append the threshold | ||
result.addAll(bnToU8a(threshold, bitLength: 16)); | ||
|
||
return blake2bDigest(Uint8List.fromList(result)); | ||
} | ||
|
||
static String createMultiSigAddress(List<String> signatories, int threshold, | ||
{int ss58Format = 42}) { | ||
return Address( | ||
prefix: ss58Format, | ||
pubkey: createMultiSigBytes( | ||
signatories | ||
.map((address) => Address.decode(address).pubkey) | ||
.toList(), | ||
threshold)) | ||
.encode(); | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
part of polkadart_keyring; | ||
|
||
Uint8List blake2bDigest(Uint8List data) { | ||
final digest = Blake2bDigest(digestSize: 32); | ||
digest.update(data, 0, data.length); | ||
final output = Uint8List(32); | ||
digest.doFinal(output, 0); | ||
return output; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
part of polkadart_keyring; | ||
|
||
// Little endian | ||
Uint8List bnToU8a(int? value, | ||
{int bitLength = -1, bool isLittleEndian = true, bool isNegative = false}) { | ||
if (value == null) { | ||
return bitLength == -1 ? Uint8List(1) : Uint8List((bitLength + 7) >> 3); | ||
} | ||
|
||
BigInt valueBn = BigInt.from(value); | ||
|
||
final int byteLength = | ||
bitLength == -1 ? (valueBn.bitLength + 7) >> 3 : ((bitLength + 7) >> 3); | ||
|
||
final Uint8List output = Uint8List(byteLength); | ||
if (isNegative) { | ||
valueBn = valueBn.toUnsigned(byteLength * 8); | ||
} | ||
|
||
final List<int> bytes = _bigIntToBytes(valueBn, byteLength, isLittleEndian); | ||
output.setAll(0, bytes); | ||
|
||
return output; | ||
} | ||
|
||
List<int> _bigIntToBytes(BigInt number, int size, bool isLittleEndian) { | ||
final List<int> result = List.filled(size, 0); | ||
int i = 0; | ||
while (number > BigInt.zero && i < size) { | ||
result[isLittleEndian ? i : (size - i - 1)] = | ||
(number & BigInt.from(0xff)).toInt(); | ||
number = number >> 8; | ||
i++; | ||
} | ||
return result; | ||
} | ||
|
||
int uint8ListCompare(Uint8List a, Uint8List b) { | ||
int i = 0; | ||
while (true) { | ||
final overA = i >= a.length; | ||
final overB = i >= b.length; | ||
if (overA && overB) { | ||
// both ends reached | ||
return 0; | ||
} else if (overA) { | ||
// a has no more data, b has data | ||
return -1; | ||
} else if (overB) { | ||
// b has no more data, a has data | ||
return 1; | ||
} else if (a[i] != b[i]) { | ||
// the number in this index doesn't match | ||
// (we don't use u8aa[i] - u8ab[i] since that doesn't match with localeCompare) | ||
return a[i] > b[i] ? 1 : -1; | ||
} | ||
i++; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import 'dart:typed_data'; | ||
import 'package:polkadart_keyring/polkadart_keyring.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
void main() { | ||
test('creates a valid multikey (aligning with Rust, needs sorting)', () { | ||
final result = MultiSig.createMultiSigBytes([ | ||
Uint8List.fromList([1, 0, 0, 0, 0, 0, 0, 0]), | ||
Uint8List.fromList([3, 0, 0, 0, 0, 0, 0, 0]), | ||
Uint8List.fromList([2, 0, 0, 0, 0, 0, 0, 0]) | ||
], 2); | ||
|
||
expect( | ||
result.toList().toString(), | ||
Uint8List.fromList([ | ||
67, | ||
151, | ||
196, | ||
155, | ||
179, | ||
207, | ||
47, | ||
123, | ||
90, | ||
2, | ||
35, | ||
54, | ||
162, | ||
111, | ||
241, | ||
226, | ||
88, | ||
148, | ||
54, | ||
193, | ||
252, | ||
195, | ||
93, | ||
101, | ||
16, | ||
5, | ||
93, | ||
101, | ||
186, | ||
186, | ||
254, | ||
79 | ||
]).toList().toString()); | ||
}); | ||
|
||
test('creates a valid multikey for the address.', () { | ||
final result = MultiSig.createMultiSigAddress([ | ||
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', | ||
'5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', | ||
'5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y' | ||
], 2); | ||
|
||
expect(result, '5DjYJStmdZ2rcqXbXGX7TW85JsrW6uG4y9MUcLq2BoPMpRA7'); | ||
}); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to put here in the docs that 2 is the threshold and what it means, here you can find a reference text: https://wiki.polkadot.network/docs/learn-account-multisig