安全多方计算之SPDZ开源库语法详解——Array

安全类型:Array (Array accessible by public index.)

所有代码的头两行:

from Compiler import types
n = 5

无特殊说明,测试代码的编译命令:test_array是我的文件名。

./compile.py test_array

测试代码的执行命令:

./emulate.x test_array

 目录

1. __init__()

2. assign(self, other, base=0)

3. assign_all

4. __getitem__()

5.  __setitem__()

6.  __len__(), total_size()

7. __iter__()

8. same_shape()

9.  __str__()

10.  create_from()

11.  reveal()、reveal_list()、reveal_nested()

12. get()

13.  get_address()

14.get_vector 和 get_part_vector

15. get_mem_value()

16. get_slice()

17. get_range()

18. set_range()

19. alloc()、delete()

20. _load(), _store()

21. expand_to_vector()

22.  shuffle()

23. input_from()

24. 运算



1. __init__()

__init__(lengthvalue_typeaddress=Nonedebug=Nonealloc=True)

Parameters:
  • length – compile-time integer (int) or None for unknown length
  • value_type – basic type
  • address – if given (regint/int), the array will not be allocated
# test code

n = 5

a = Array(n,sfix)
print_ln("%s", a.reveal())

a.__init__(6,sint)
print_ln("%s", a.reveal())

Array.__init__(a,7,cint)
print_ln("%s", a.reveal())

执行结果: 

2. assign(self, other, base=0)

作用:为数组赋值。other代表为数组赋的值的数组。

a = Array(n, sfix)
b = Array(n, sfix)
t = [2,15,21,33,41]
t1 = [100,101,200,12,90]
a.assign(t)
print_ln("a = %s", a.reveal())
b.assign(a)
print_ln("b = %s", b.reveal())

a.assign_vector(t1)
print_ln("a = %s", a.reveal())
a.assign_part_vector(t)
print_ln("a = %s", a.reveal())

另外两个函数与assign一模一样。也就是assign=assign_vector=assign_part_vector。

3. assign_all

assign_all(valueuse_threads=Trueconv=True)

Assign the same value to all entries.

Parameters:value – convertible to basic type

 为一个数组所有元素赋相同的值。

a = Array(n, sfix)

a.assign_all(45)
print_ln("a = %s", a.reveal())

4. __getitem__()

__getitem__(index)

Reading from array.

Parameters:index – public (regint/cint/int/slice)
Returns:array if slice is given, basic type otherwise

获得数组指定位置的值。

a = Array(n, sfix)
t = [2,15,21,33,41]
a.assign(t)
b = Array.__getitem__(a,1)
print_ln("a = %s", a.__getitem__(2).reveal())
print_ln("b = %s", b.reveal())

 

5.  __setitem__()

__setitem__(indexvalue)

Writing to array.

Parameters:
  • index – public (regint/cint/int)
  • value – convertible for relevant basic type

为指定位置的元素赋值。

a = Array(n, sfix)
a.assign([2,15,21,33,41])
print_ln("a = %s", a.reveal())
a.__setitem__(2,99)
print_ln("a = %s", a.reveal())

 

6.  __len__(), total_size()

返回数组的长度。

a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
print_ln("a = %s", a.__len__())
print_ln("a = %s", a.total_size())

这两个函数应该是有区别的,但是我还不知道。想仔细探究的同学可以看看他们的源码。欢迎评论区交流。

7. __iter__()

返回元素的值。源码中使用到了表达式yield,不懂的可以百度下,这里不多解释了。

#源代码
 def __iter__(self):
        for i in range(self.length):
            yield self[i]
#test code
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
b = a.__iter__()
print_ln("a = %s", b)
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())

8. same_shape()

创建一个和原来数组相同“形状”的数组。这里的“形状”是指新数组与原数组长度相同,元素值的类型相同,但是元素的值并不是复制原数组。

a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
b = Array.same_shape(a)
print_ln("a = %s", a.reveal())
print_ln("b = %s", b.reveal())

9.  __str__()

输出数组的信息,包括:数组元素类型、长度、地址。

a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
print_ln("a = %s", a.__str__())
b = Array(10, cint)
b.assign([2,15,21,1,23,34,11,33,41,12])
print_ln("b = %s", b.__str__())

10.  create_from()

将一个迭代器转换为一个数组。这是一个类方法(@classmethod)。类方法与某个具体实例本身无关,可以用实例调用它执行相应功能。在这个例子中,我们将迭代器l转换为数组b,迭代器l的属性与数组l0有关,与数组a无关,我们只是使用实例a来调用了函数,但是并没有用到实例a本身的属性和值。

l0 = Array(5, sint)
l = iter(l0)
a = Array(10, cint)
b = a.create_from(l)
print_ln("b = %s", b.reveal())

11.  reveal()、reveal_list()、reveal_nested()

返回整个数组的值,其中后两个函数将数组转换成立list输出,这两个函数完全相等(reveal_list=reveal_nested)。

a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
print_ln("a = %s", a.reveal())
print_ln("a = %s", a.reveal_list())
print_ln("a = %s", a.reveal_nested())

12. get()

get(self, indices)。得到指定位置的值。

a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
@for_range(6)
def _(i):
	t = sint(i)
	c = a.get(t.reveal())
	print_ln("a[%s] = %s",i, c.reveal())

13.  get_address()

get_address(self, index)。获取数组指定位置的地址。

a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
@for_range(6)
def _(i):
	print_ln("a[%s] = %s, a[%s].adress = %s", i, a[i].reveal(), i, a.get_address(i))

14.get_vector 和 get_part_vector

get_vector(self, base=0, size=None)。这两个函数是等价的。

获取从指定位置(base)开始,指定长度(size)的数组。

a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = a.get_vector(2,5)
c = Array.get_part_vector(a,3,6)
for i in range(0,b.__len__()):
	print_str("%s ",b[i].reveal())
print_ln()
for i in range(0,c.__len__()):
	print_str("%s ",c[i].reveal())
print_ln()

数组b从数组a的二元素(a[2])开始,截取长度为5

数组c从数组a的三元素(a[3])开始,截取长度为6

注意,数组b,c并不是Array类型的,不能使用

print_ln("b = %s",b.reveal())

来打印,否则会报错。也不能使用@for_range()循环来打印,只能用普通的循环。数组b、c根据函数名字可能是个vector类型,但是spdz并没有vector这个类型,所以不确定它是什么类型。

15. get_mem_value()

get_mem_value(self, index)

返回数组指定位置的值。这里的返回值是一个MemValue类型。

a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])

b = a.get_mem_value(2)
print_ln("b = %s", b.reveal())

16. get_slice()

get_slice(self, index). 我也不知道这函数是干嘛的,有什么意义。Sorry~~~

传入的index是一个类,这个类包含三个属性:start、stop、step。调用函数就会输出传入的类的属性。

class index:
    def __init__(self):
        self.start = 0
        self.stop = 0
        self.step = 0
i = index()
i.start = 12
i.stop = 554 
i.step = 4433
a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = a.get_slice(i)
print_ln("b = %s", b)

17. get_range()

get_range(self, start, size)  获取从指定位置开始,指定长度的数组。与get_vector类似,但是它返回的是list类型,但是元素的类型可以是任何安全类型。

所以打印时要注意,如果你加reveal()会报错list没有这个方法,而不加会报错安全类型的值不能直接打印。

我的方法是把他转换成了Array类型,这样就可以加reve()打印了。

a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])

b = a.get_range(2,5)
c = Array(len(b),sfix)
c.assign(b)
print_ln("c = %s", c.reveal())

18. set_range()

set_range(self, start, values)

对数组,从指定位置开始,为该位置及以后的元素赋值。start是一个数,values是一个list

a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = [1,2,3,4]
a.set_range(3,b)
print_ln("a = %s", a.reveal())

19. alloc()、delete()

alloc(): 如果一个数组没有分配内存地址,则为数组分配地址。一般情况你定义一个Array他会自动分配地址的。

delete(): 删除一个数组。通过删除内存地址的方式。

a = Array(10,sfix)
print_ln("a.address: %s", a.address)
a.delete()
print_ln("delete: %s", a.address)
a.alloc()
print_ln("alloc: %s", a.address)

20. _load(), _store()

通过内存地址的方式访问数组数据

_load(self, address):访问内存地址为“address”的数据并返回该数据。

_store(self, value, address):对内存地址为“address”的元素赋值(value)

a = Array(10,sfix)
print_ln("a.address: %s", a.address)
print_ln("a = %s", a.reveal())

b = Array._load(a,a.get_address(1))

print_ln("b = %s", b.reveal())

a._store(12,a.get_address(1))

print_ln("a = %s", a.reveal())

21. expand_to_vector()

expand_to_vector(self, index, size) 

返回:复制size个第index个位置的值组成一个数组,这个数组不是Array类型也不是list,与get_vector的返回值类型相同。

a = Array(10,sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
print_ln("a = %s", a.reveal())
b = a.expand_to_vector(2,5)
for i in range(b.__len__()):
	print_str("%s ",b[i].reveal())
print_ln()

22.  shuffle()

shuffle(self)  shuffle就是洗牌的意思。这个函数可以将一个数组的元素重新打乱顺序,没有返回值。

a = Array(10,sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
print_ln("a = %s", a.reveal())
for i in range(5):
	a.shuffle()
	print_ln("a = %s", a.reveal())

23. input_from()

input_from(self, player, budget=None, raw=False)  从参与者手中接收数据。

a = Array(5,sfix)
a.input_from(0)
print_ln("a = %s", a.reveal())

编译程序:

生成证书:

输入数据:

执行程序:

24. 运算

这里的运算都被当作向量运算,它将Array类型转换成之前提到过的“vector”,然后进行运算。返回的结果也是“vector”

__add__() = __radd__():加法:__add__(self, other)   

__mul__() = __rmul__():乘法:__mul__(self, value)   元素的值*value

__pow__():幂:__pow__(self, value) 元素的值**value

__sub__():减法:__sub__(self, other)

注意,编译程序时要指定环的模数大小:

./compile.py -R 128 test_array
a = Array(5,sfix)
b = Array(5,sfix)
a.assign([3,4,5,6,7])
b.assign([2,2,2,2,2])
print_ln("a = %s", a.reveal())
print_ln("b = %s", b.reveal())
c = a.__add__(b.get_vector())
print_str("add = ")
for i in range(c.__len__()):
	print_str("%s ",c[i].reveal())
print_ln()
 
d = a.__sub__(b.get_vector())
print_str("sub = ")
for i in range(d.__len__()):
	print_str("%s ",d[i].reveal())
print_ln()

c = a.__mul__(3)
print_str("mul = ")
for i in range(c.__len__()):
	print_str("%s ",c[i].reveal())
print_ln()

c = a.__pow__(3)
print_str("pow = ")
for i in range(c.__len__()):
	print_str("%s ",c[i].reveal())
print_ln()

这里就是Array类型的所有方法了,历时2天半终于写完。呼~~~

大家看到有什么错误的、不对的或者要补充的、要解答的,欢迎在评论区交流~~~

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值