Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
DisSys Inc.
bsc-shamir
Commits
e815b3a5
Commit
e815b3a5
authored
Jun 03, 2020
by
Anders Jensen Løvig
Browse files
Max-subset agreement
parent
3e09f85e
Pipeline
#21827
failed with stages
in 1 minute and 3 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
crypto/schnorr/schnorr.go
View file @
e815b3a5
...
...
@@ -116,7 +116,7 @@ func (s *Params) VerifyDisjunction(p0, p1 *Proof) bool {
func
Hash
(
ls
...*
big
.
Int
)
*
big
.
Int
{
hash
:=
sha512
.
New
()
for
_
,
e
:=
range
ls
{
hash
.
Write
(
e
.
Bytes
())
_
,
_
=
hash
.
Write
(
e
.
Bytes
())
}
sum
:=
hash
.
Sum
([]
byte
{})
return
new
(
big
.
Int
)
.
SetBytes
(
sum
)
...
...
election/agreement.go
View file @
e815b3a5
package
election
import
(
"bsc-shamir/crypto/pedersen"
"fmt"
"log"
"sync"
"github.com/gonum/stat/combin"
...
...
@@ -17,6 +17,7 @@ type Agreement struct {
// The minimum servers required for being able to tally
required
int
// Map of ballot lists receveid from servers
ourList
BallotList
ballotLists
map
[
UniqueID
]
BallotList
}
...
...
@@ -40,80 +41,40 @@ func (a *Agreement) AddList(serverID UniqueID, ballotList map[string]uuid.UUID)
return
nil
}
func
(
a
*
Agreement
)
TallyList
()
[]
uuid
.
UUID
{
for
_
,
ll
:=
range
a
.
ballotLists
{
list
:=
make
([]
uuid
.
UUID
,
0
,
len
(
ll
))
for
_
,
id
:=
range
ll
{
list
=
append
(
list
,
id
)
}
return
list
func
(
a
*
Agreement
)
TallyList
()
([]
uuid
.
UUID
,
error
)
{
a
.
Lock
()
defer
a
.
Unlock
()
bls
:=
make
([]
BallotList
,
0
,
len
(
a
.
ballotLists
))
for
_
,
b
:=
range
a
.
ballotLists
{
bls
=
append
(
bls
,
b
)
}
panic
(
"Fuck"
)
}
type
Whitelist
map
[
uuid
.
UUID
]
pedersen
.
Proof
type
Judge
struct
{
mutex
sync
.
Mutex
Threadshold
int
Points
map
[
uuid
.
UUID
]
int
Answers
map
[
uuid
.
UUID
]
pedersen
.
Proof
BallotIDs
[]
uuid
.
UUID
}
func
NewJudge
(
threadshold
int
,
box
*
BallotBox
)
*
Judge
{
m
:=
len
(
box
.
ballots
)
j
:=
&
Judge
{
mutex
:
sync
.
Mutex
{},
Threadshold
:
threadshold
,
Points
:
make
(
map
[
uuid
.
UUID
]
int
,
m
),
Answers
:
make
(
map
[
uuid
.
UUID
]
pedersen
.
Proof
,
m
),
BallotIDs
:
[]
uuid
.
UUID
{},
}
for
_
,
id
:=
range
box
.
Filter
()
{
ballot
:=
box
.
ballots
[
id
]
j
.
Answers
[
id
]
=
ballot
.
Commits
j
.
Points
[
id
]
=
0
j
.
BallotIDs
=
append
(
j
.
BallotIDs
,
id
)
}
return
j
}
hashes
:=
MaxSubset
(
a
.
required
,
bls
)
func
(
j
*
Judge
)
HandleWhitelist
(
wl
Whitelist
)
{
j
.
mutex
.
Lock
()
defer
j
.
mutex
.
Unlock
()
for
_
,
id
:=
range
j
.
BallotIDs
{
proof
:=
wl
[
id
]
answer
:=
j
.
Answers
[
id
]
if
proof
.
Equals
(
answer
)
{
j
.
Points
[
id
]
++
list
:=
make
([]
uuid
.
UUID
,
0
,
len
(
a
.
ourList
))
for
h
:=
range
hashes
{
if
id
,
ok
:=
a
.
ourList
[
h
];
ok
{
list
=
append
(
list
,
id
)
delete
(
hashes
,
h
)
}
}
}
func
(
j
*
Judge
)
GoodIds
()
[]
uuid
.
UUID
{
j
.
mutex
.
Lock
()
defer
j
.
mutex
.
Unlock
()
good
:=
[]
uuid
.
UUID
{}
for
_
,
id
:=
range
j
.
BallotIDs
{
if
j
.
Points
[
id
]
>=
j
.
Threadshold
{
good
=
append
(
good
,
id
)
}
if
len
(
hashes
)
!=
0
{
return
nil
,
fmt
.
Errorf
(
"missing %d ballots to tally"
,
len
(
hashes
))
}
return
good
return
list
,
nil
}
func
MaxSubset
(
t
int
,
superset
[][]
uuid
.
UUID
)
map
[
uuid
.
UUID
]
bool
{
n
:=
len
(
superset
)
func
MaxSubset
(
t
int
,
ballotLists
[]
BallotList
)
map
[
string
]
bool
{
n
:=
len
(
ballotLists
)
combis
:=
combin
.
Combinations
(
n
,
t
)
subsets
:=
make
([]
map
[
uuid
.
UUID
]
bool
,
len
(
combis
),
n
)
log
.
Printf
(
"N: %d, combis: %d
\n
"
,
n
,
len
(
combis
))
subsets
:=
make
([]
map
[
string
]
bool
,
len
(
combis
),
n
)
for
i
,
ls
:=
range
combis
{
sets
:=
[][]
uuid
.
UUID
{}
sets
:=
make
([]
BallotList
,
0
,
len
(
ls
))
for
_
,
i
:=
range
ls
{
sets
=
append
(
sets
,
superset
[
i
])
sets
=
append
(
sets
,
ballotLists
[
i
])
}
subsets
[
i
]
=
Intersection
(
sets
)
}
...
...
@@ -126,17 +87,17 @@ func MaxSubset(t int, superset [][]uuid.UUID) map[uuid.UUID]bool {
return
subsets
[
max
]
}
func
Intersection
(
superset
[]
[]
uuid
.
UUID
)
map
[
uuid
.
UUID
]
bool
{
section
:=
make
(
map
[
uuid
.
UUID
]
int
,
len
(
superset
[
0
]))
func
Intersection
(
superset
[]
BallotList
)
map
[
string
]
bool
{
section
:=
make
(
map
[
string
]
int
,
len
(
superset
[
0
]))
for
_
,
set
:=
range
superset
{
for
_
,
e
:=
range
set
{
section
[
e
]
++
for
hash
:=
range
set
{
section
[
hash
]
++
}
}
set
:=
make
(
map
[
uuid
.
UUID
]
bool
)
for
uuid
,
num
:=
range
section
{
set
:=
make
(
map
[
string
]
bool
)
for
hash
,
num
:=
range
section
{
if
num
>=
len
(
superset
)
{
set
[
uuid
]
=
true
set
[
hash
]
=
true
}
}
return
set
...
...
election/agreement_test.go
View file @
e815b3a5
...
...
@@ -12,33 +12,34 @@ func TestIntersection(t *testing.T) {
for
i
:=
0
;
i
<
N
;
i
++
{
elem
[
i
]
=
uuid
.
New
()
}
superset
:=
[]
[]
uuid
.
UUID
{
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
3
]},
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
4
]},
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
5
]},
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
6
]},
superset
:=
[]
BallotList
{
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"3"
:
elem
[
3
]},
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"4"
:
elem
[
4
]},
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"5"
:
elem
[
5
]},
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"6"
:
elem
[
6
]},
}
subset
:=
Intersection
(
superset
)
if
!
subset
[
elem
[
0
]
]
{
t
.
Fail
()
if
!
subset
[
"0"
]
{
t
.
Error
()
}
if
!
subset
[
elem
[
1
]
]
{
t
.
Fail
()
if
!
subset
[
"1"
]
{
t
.
Error
()
}
if
!
subset
[
elem
[
2
]
]
{
t
.
Fail
()
if
!
subset
[
"2"
]
{
t
.
Error
()
}
if
subset
[
elem
[
3
]
]
{
t
.
Fail
()
if
subset
[
"3"
]
{
t
.
Error
()
}
if
subset
[
elem
[
4
]
]
{
t
.
Fail
()
if
subset
[
"4"
]
{
t
.
Error
()
}
if
subset
[
elem
[
5
]
]
{
t
.
Fail
()
if
subset
[
"5"
]
{
t
.
Error
()
}
if
subset
[
elem
[
6
]
]
{
t
.
Fail
()
if
subset
[
"6"
]
{
t
.
Error
()
}
}
...
...
@@ -48,33 +49,33 @@ func TestMaxSubset(t *testing.T) {
for
i
:=
0
;
i
<
N
;
i
++
{
elem
[
i
]
=
uuid
.
New
()
}
superset
:=
[]
[]
uuid
.
UUID
{
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
3
]},
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
4
]},
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
5
]},
{
elem
[
0
],
elem
[
1
],
elem
[
2
],
elem
[
6
]},
{
elem
[
6
]},
superset
:=
[]
BallotList
{
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"3"
:
elem
[
3
]
,
"4"
:
elem
[
4
]
},
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"4"
:
elem
[
4
]},
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"5"
:
elem
[
5
]},
{
"0"
:
elem
[
0
],
"1"
:
elem
[
1
],
"2"
:
elem
[
2
],
"4"
:
elem
[
4
],
"6"
:
elem
[
6
]},
{
"6"
:
elem
[
6
]},
}
subset
:=
MaxSubset
(
4
,
superset
)
if
!
subset
[
elem
[
0
]
]
{
t
.
Fail
()
if
!
subset
[
"0"
]
{
t
.
Error
()
}
if
!
subset
[
elem
[
1
]
]
{
t
.
Fail
()
if
!
subset
[
"1"
]
{
t
.
Error
()
}
if
!
subset
[
elem
[
2
]
]
{
t
.
Fail
()
if
!
subset
[
"2"
]
{
t
.
Error
()
}
if
subset
[
elem
[
3
]
]
{
t
.
Fail
()
if
subset
[
"3"
]
{
t
.
Error
()
}
if
subset
[
elem
[
4
]
]
{
t
.
Fail
()
if
subset
[
"4"
]
{
t
.
Error
()
}
if
subset
[
elem
[
5
]
]
{
t
.
Fail
()
if
subset
[
"5"
]
{
t
.
Error
()
}
if
subset
[
elem
[
6
]
]
{
t
.
Fail
()
if
subset
[
"6"
]
{
t
.
Error
()
}
}
election/election.go
View file @
e815b3a5
...
...
@@ -257,15 +257,18 @@ func (election *Election) nextPhase(reason Reason) {
// Only tally if we have ballots
if
election
.
ballotBox
.
Size
()
!=
0
{
list
:=
election
.
Agreement
.
TallyList
()
tally
:=
election
.
ballotBox
.
Tally
(
list
)
election
.
Status
.
TalliedServers
[
election
.
ServerID
]
=
true
err
:=
election
.
tallyBox
.
Put
(
tally
)
if
err
!=
nil
{
panic
(
err
)
// Should not happen
list
,
err
:=
election
.
Agreement
.
TallyList
()
if
err
==
nil
{
tally
:=
election
.
ballotBox
.
Tally
(
list
)
election
.
Status
.
TalliedServers
[
election
.
ServerID
]
=
true
err
=
election
.
tallyBox
.
Put
(
tally
)
if
err
!=
nil
{
panic
(
err
)
// Should not happen
}
election
.
server
.
Broadcast
(
network
.
NewMessage
(
MsgTally
,
tally
))
break
}
election
.
server
.
Broadcast
(
network
.
NewMessage
(
MsgTally
,
tally
))
break
log
.
Println
(
"Should really wait for tallies from other servers !!! :D"
)
}
fallthrough
...
...
election/election_test.go
View file @
e815b3a5
...
...
@@ -93,17 +93,22 @@ func benchmarkTally(votecount, serverCount, reqServer int, b *testing.B) {
//Setup
b
.
StopTimer
()
box
:=
NewBallotBox
(
big
.
NewInt
(
1
),
common
.
DefaultParams
())
judge
:=
NewJudge
(
reqServer
,
box
)
goodIds
:=
judge
.
GoodIds
()
id
:=
UniqueID
(
"1"
)
for
i
:=
0
;
i
<
votecount
;
i
++
{
_
=
box
.
Put
(
CreateBallots
(
reqServer
,
createXS
(
serverCount
),
big
.
NewInt
(
1
))[
id
])
}
ballotList
:=
box
.
ballotList
()
ids
:=
make
([]
uuid
.
UUID
,
0
,
len
(
ballotList
))
for
_
,
id
:=
range
ballotList
{
ids
=
append
(
ids
,
id
)
}
//Actual benchmark
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
box
.
Tally
(
goodI
ds
)
box
.
Tally
(
i
ds
)
}
}
...
...
@@ -158,10 +163,13 @@ func benchmarkCombine(votecount, serverCount, reqServer int, b *testing.B) {
_
=
ballotbox
.
Put
(
ballot
[
ID
])
}
judge
:=
NewJudge
(
reqServer
,
ballotbox
)
goodIds
:=
judge
.
GoodIds
()
ballotList
:=
ballotbox
.
ballotList
()
ids
:=
make
([]
uuid
.
UUID
,
0
,
len
(
ballotList
))
for
_
,
id
:=
range
ballotList
{
ids
=
append
(
ids
,
id
)
}
tally
:=
ballotbox
.
Tally
(
goodI
ds
)
tally
:=
ballotbox
.
Tally
(
i
ds
)
for
i
:=
0
;
i
<
reqServer
;
i
++
{
_
=
tallyBoxes
[
0
]
.
Put
(
tally
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment