




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第python區(qū)塊鏈地址的簡(jiǎn)版實(shí)現(xiàn)本文根據(jù)/liuchengxu/blockchain-tutorial的內(nèi)容,用python實(shí)現(xiàn)的,但根據(jù)個(gè)人的理解進(jìn)行了一些修改,大量引用了原文的內(nèi)容。文章末尾有本節(jié)完整源碼實(shí)現(xiàn)地址。
在上一篇文章中,我們已經(jīng)初步實(shí)現(xiàn)了交易。相信你應(yīng)該了解了交易中的一些天然屬性,這些屬性沒(méi)有絲毫個(gè)人色彩的存在:在比特幣中,沒(méi)有用戶賬戶,不需要也不會(huì)在任何地方存儲(chǔ)個(gè)人數(shù)據(jù)(比如姓名,護(hù)照號(hào)碼或者SSN)。但是,我們總要有某種途徑識(shí)別出你是交易輸出的所有者(也就是說(shuō),你擁有在這些輸出上鎖定的幣)。這就是比特幣地址(address)需要完成的使命。在上一篇中,我們把一個(gè)由用戶定義的任意字符串當(dāng)成是地址,現(xiàn)在我們將要實(shí)現(xiàn)一個(gè)跟比特幣一樣的真實(shí)地址。
比特幣地址
這就是一個(gè)真實(shí)的比特幣地址:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa。這是史上第一個(gè)比特幣地址,據(jù)說(shuō)屬于中本聰。比特幣地址是完全公開(kāi)的,如果你想要給某個(gè)人發(fā)送幣,只需要知道他的地址就可以了。但是,地址(盡管地址也是獨(dú)一無(wú)二的)并不是用來(lái)證明你是一個(gè)錢包所有者的信物。實(shí)際上,所謂的地址,只不過(guò)是將公鑰表示成人類可讀的形式而已,因?yàn)樵墓€人類很難閱讀。在比特幣中,你的身份(identity)就是一對(duì)(或者多對(duì))保存在你的電腦(或者你能夠獲取到的地方)上的公鑰(publickey)和私鑰(privatekey)。比特幣基于一些加密算法的組合來(lái)創(chuàng)建這些密鑰,并且保證了在這個(gè)世界上沒(méi)有其他人能夠取走你的幣,除非拿到你的密鑰。下面,讓我們來(lái)討論一下這些算法到底是什么。
公鑰加密(public-keycryptography)算法使用的是成對(duì)的密鑰:公鑰和私鑰。公鑰并不是敏感信息,可以告訴其他人。但是,私鑰絕對(duì)不能告訴其他人:只有所有者(owner)才能知道私鑰,能夠識(shí)別,鑒定和證明所有者身份的就是私鑰。在加密貨幣的世界中,你的私鑰代表的就是你,私鑰就是一切。
本質(zhì)上,比特幣錢包也只不過(guò)是這樣的密鑰對(duì)而已。當(dāng)你安裝一個(gè)錢包應(yīng)用,或是使用一個(gè)比特幣客戶端來(lái)生成一個(gè)新地址時(shí),它就會(huì)為你生成一對(duì)密鑰。在比特幣中,誰(shuí)擁有了私鑰,誰(shuí)就可以控制所有發(fā)送到這個(gè)公鑰的幣。
私鑰和公鑰只不過(guò)是隨機(jī)的字節(jié)序列,因此它們無(wú)法在屏幕上打印,人類也無(wú)法通過(guò)肉眼去讀取。這就是為什么比特幣使用了一個(gè)轉(zhuǎn)換算法,將公鑰轉(zhuǎn)化為一個(gè)人類可讀的字符串(也就是我們看到的地址)。
如果你用過(guò)比特幣錢包應(yīng)用,很可能它會(huì)為你生成一個(gè)助記符。這樣的助記符可以用來(lái)替代私鑰,并且可以被用于生成私鑰。BIP-039已經(jīng)實(shí)現(xiàn)了這個(gè)機(jī)制。
好了,現(xiàn)在我們已經(jīng)知道了在比特幣中證明用戶身份的是私鑰。那么,比特幣如何檢查交易輸出(和存儲(chǔ)在里面的幣)的所有權(quán)呢?
在數(shù)學(xué)和密碼學(xué)中,有一個(gè)數(shù)字簽名(digitalsignature)的概念,算法可以保證:
當(dāng)數(shù)據(jù)從發(fā)送方傳送到接收方時(shí),數(shù)據(jù)不會(huì)被修改;數(shù)據(jù)由某一確定的發(fā)送方創(chuàng)建;發(fā)送方無(wú)法否認(rèn)發(fā)送過(guò)數(shù)據(jù)這一事實(shí)。
通過(guò)在數(shù)據(jù)上應(yīng)用簽名算法(也就是對(duì)數(shù)據(jù)進(jìn)行簽名),你就可以得到一個(gè)簽名,這個(gè)簽名晚些時(shí)候會(huì)被驗(yàn)證。生成數(shù)字簽名需要一個(gè)私鑰,而驗(yàn)證簽名需要一個(gè)公鑰。簽名有點(diǎn)類似于印章,比方說(shuō)我做了一幅畫,完了用印章一蓋,就說(shuō)明了這幅畫是我的作品。給數(shù)據(jù)生成簽名,就是給數(shù)據(jù)蓋了章。
為了對(duì)數(shù)據(jù)進(jìn)行簽名,我們需要下面兩樣?xùn)|西:
要簽名的數(shù)據(jù)私鑰
應(yīng)用簽名算法可以生成一個(gè)簽名,并且這個(gè)簽名會(huì)被存儲(chǔ)在交易輸入中。為了對(duì)一個(gè)簽名進(jìn)行驗(yàn)證,我們需要以下三樣?xùn)|西:
被簽名的數(shù)據(jù)簽名公鑰
簡(jiǎn)單來(lái)說(shuō),驗(yàn)證過(guò)程可以被描述為:檢查簽名是由被簽名數(shù)據(jù)加上私鑰得來(lái),并且公鑰恰好是由該私鑰生成。
數(shù)據(jù)簽名并不是加密,你無(wú)法從一個(gè)簽名重新構(gòu)造出數(shù)據(jù)。這有點(diǎn)像哈希:你在數(shù)據(jù)上運(yùn)行一個(gè)哈希算法,然后得到一個(gè)該數(shù)據(jù)的唯一表示。簽名與哈希的區(qū)別在于密鑰對(duì):有了密鑰對(duì),才有簽名驗(yàn)證。但是密鑰對(duì)也可以被用于加密數(shù)據(jù):私鑰用于加密,公鑰用于解密數(shù)據(jù)。不過(guò)比特幣并不使用加密算法。
在比特幣中,每一筆交易輸入都會(huì)由創(chuàng)建交易的人簽名。在被放入到一個(gè)塊之前,必須要對(duì)每一筆交易進(jìn)行驗(yàn)證。除了一些其他步驟,驗(yàn)證意味著:
檢查交易輸入有權(quán)使用來(lái)自之前交易的輸出檢查交易簽名是正確的
如圖,對(duì)數(shù)據(jù)進(jìn)行簽名和對(duì)簽名進(jìn)行驗(yàn)證的過(guò)程大致如下:
現(xiàn)在來(lái)回顧一個(gè)交易完整的生命周期:
起初,創(chuàng)世塊里面包含了一個(gè)coinbase交易。在coinbase交易中,沒(méi)有輸入,所以也就不需要簽名。coinbase交易的輸出包含了一個(gè)哈希過(guò)的公鑰(使用的是RIPEMD16(SHA256(PubKey))算法)當(dāng)一個(gè)人發(fā)送幣時(shí),就會(huì)創(chuàng)建一筆交易。這筆交易的輸入會(huì)引用之前交易的輸出。每個(gè)輸入會(huì)存儲(chǔ)一個(gè)公鑰(沒(méi)有被哈希)和整個(gè)交易的一個(gè)簽名。比特幣網(wǎng)絡(luò)中接收到交易的其他節(jié)點(diǎn)會(huì)對(duì)該交易進(jìn)行驗(yàn)證。除了一些其他事情,他們還會(huì)檢查:在一個(gè)輸入中,公鑰哈希與所引用的輸出哈希相匹配(這保證了發(fā)送方只能花費(fèi)屬于自己的幣);簽名是正確的(這保證了交易是由幣的實(shí)際擁有者所創(chuàng)建)。當(dāng)一個(gè)礦工準(zhǔn)備挖一個(gè)新塊時(shí),他會(huì)將交易放到塊中,然后開(kāi)始挖礦。當(dāng)新塊被挖出來(lái)以后,網(wǎng)絡(luò)中的所有其他節(jié)點(diǎn)會(huì)接收到一條消息,告訴其他人這個(gè)塊已經(jīng)被挖出并被加入到區(qū)塊鏈。當(dāng)一個(gè)塊被加入到區(qū)塊鏈以后,交易就算完成,它的輸出就可以在新的交易中被引用。
橢圓曲線加密
正如之前提到的,公鑰和私鑰是隨機(jī)的字節(jié)序列。私鑰能夠用于證明持幣人的身份,需要有一個(gè)條件:隨機(jī)算法必須生成真正隨機(jī)的字節(jié)。因?yàn)闆](méi)有人會(huì)想要生成一個(gè)私鑰,而這個(gè)私鑰意外地也被別人所有。
比特幣使用橢圓曲線來(lái)產(chǎn)生私鑰。橢圓曲線是一個(gè)復(fù)雜的數(shù)學(xué)概念,我們并不打算在這里作太多解釋(如果你真的十分好奇,可以查看這篇文章,注意:有很多數(shù)學(xué)公式?。┪覀冎灰肋@些曲線可以生成非常大的隨機(jī)數(shù)就夠了。在比特幣中使用的曲線可以隨機(jī)選取在0與2^2^56(大概是10^77,而整個(gè)可見(jiàn)的宇宙中,原子數(shù)在10^78到10^82之間)的一個(gè)數(shù)。有如此高的一個(gè)上限,意味著幾乎不可能發(fā)生有兩次生成同一個(gè)私鑰的事情。
比特幣使用的是ECDSA(EllipticCurveDigitalSignatureAlgorithm)算法來(lái)對(duì)交易進(jìn)行簽名,我們也會(huì)使用該算法。
Base58
回到上面提到的比特幣地址:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?,F(xiàn)在,我們已經(jīng)知道了這是公鑰用人類可讀的形式表示而已。如果我們對(duì)它進(jìn)行解碼,就會(huì)看到公鑰的本來(lái)面目(16進(jìn)制表示的字節(jié)):
0062E907B15CBF27D5425399EBF6F0FB50EBB88F18C29B7D93
比特幣使用Base58算法將公鑰轉(zhuǎn)換成人類可讀的形式。這個(gè)算法跟著名的Base64很類似,區(qū)別在于它使用了更短的字母表:為了避免一些利用字母相似性的攻擊,從字母表中移除了一些字母。也就是,沒(méi)有這些符號(hào):0(零),O(大寫的o),I(大寫的i),l(小寫的L),因?yàn)檫@幾個(gè)字母看著很像。另外,也沒(méi)有+和/符號(hào)。
下圖是從一個(gè)公鑰獲得一個(gè)地址的過(guò)程:
因此,上面提到的公鑰解碼后包含三個(gè)部分:
VersionPublickeyhashChecksum
0062E907B15CBF27D5425399EBF6F0FB50EBB88F18C29B7D93
由于哈希函數(shù)是單向的(也就說(shuō)無(wú)法逆轉(zhuǎn)回去),所以不可能從一個(gè)哈希中提取公鑰。不過(guò)通過(guò)執(zhí)行哈希函數(shù)并進(jìn)行哈希比較,我們可以檢查一個(gè)公鑰是否被用于哈希的生成。
好了,所有細(xì)節(jié)都已就緒,來(lái)寫代碼吧。很多概念只有當(dāng)寫代碼的時(shí)候,才能理解地更透徹。
我們先從錢包Wallet結(jié)構(gòu)開(kāi)始:
classWallet(object):
#hexversion
VERSION=b'\0'
def__init__(self,private_key):
self._private_key=private_key
self._public_key=private_key.get_verifying_key()
self._address=''
@classmethod
defgenerate_wallet(cls,curve=SECP256k1):
generateawallet
sign_key=SigningKey.generate(curve=curve)
returncls(sign_key)
一個(gè)錢包只有一個(gè)密鑰對(duì)而已。我們需要Wallets類型來(lái)保存多個(gè)錢包的組合,將它們保存到文件中,或者從文件中進(jìn)行加載。Wallet的構(gòu)造函數(shù)會(huì)生成一個(gè)新的密鑰對(duì)。generate_wallet函數(shù)非常直觀:ECDSA基于橢圓曲線,所以我們需要一個(gè)橢圓曲線。接下來(lái),使用橢圓生成一個(gè)私鑰。
@property
defaddress(self):
ifnotself._address:
prv_addr=self.VERSION+self._hash_public_key()
self._address=base58.b58encode_check(prv_addr)
returnself._address
以上是地址的生成,使用base58的庫(kù)來(lái)實(shí)現(xiàn),通過(guò)pipinstallbase58即可安裝,我們也可以直接下載源碼放在工程目錄下使用。使用該庫(kù)我們就不用重復(fù)造輪子了。
至此,就可以得到一個(gè)真實(shí)的比特幣地址,你甚至可以在查看它的余額。不過(guò)我可以負(fù)責(zé)任地說(shuō),無(wú)論生成一個(gè)新的地址多少次,檢查它的余額都是0。這就是為什么選擇一個(gè)合適的公鑰加密算法是如此重要:考慮到私鑰是隨機(jī)數(shù),生成同一個(gè)數(shù)字的概率必須是盡可能地低。理想情況下,必須是低到永遠(yuǎn)不會(huì)重復(fù)。
另外,注意:你并不需要連接到一個(gè)比特幣節(jié)點(diǎn)來(lái)獲得一個(gè)地址。地址生成算法使用的多種開(kāi)源算法可以通過(guò)很多編程語(yǔ)言和庫(kù)實(shí)現(xiàn)。
注意,現(xiàn)在我們已經(jīng)不再需要script_pub_key和script_sig字段,因?yàn)槲覀儾粫?huì)實(shí)現(xiàn)一個(gè)腳本語(yǔ)言。相反,script_sig會(huì)被分為signature和pub_key字段,script_pub_key被重命名為PubKeyHash。我們會(huì)實(shí)現(xiàn)跟比特幣里一樣的輸出鎖定/解鎖和輸入簽名邏輯,不同的是我們會(huì)通過(guò)方法(method)來(lái)實(shí)現(xiàn)。
use_key方法檢查輸入使用了指定密鑰來(lái)解鎖一個(gè)輸出。注意到輸入存儲(chǔ)的是原生的公鑰(也就是沒(méi)有被哈希的公鑰),但是這個(gè)函數(shù)要求的是哈希后的公鑰。is_locked_with_key檢查是否提供的公鑰哈希被用于鎖定輸出。這是一個(gè)use_key的輔助函數(shù),并且它們都被用于find_unspent_transactions來(lái)形成交易之間的聯(lián)系。
lock只是簡(jiǎn)單地鎖定了一個(gè)輸出。當(dāng)我們給某個(gè)人發(fā)送幣時(shí),我們只知道他的地址,因?yàn)檫@個(gè)函數(shù)使用一個(gè)地址作為唯一的參數(shù)。然后,地址會(huì)被解碼,從中提取出公鑰哈希并保存在pub_key_hash字段。
交易必須被簽名,因?yàn)檫@是比特幣里面保證發(fā)送方不會(huì)花費(fèi)屬于其他人的幣的唯一方式。如果一個(gè)簽名是無(wú)效的,那么這筆交易就會(huì)被認(rèn)為是無(wú)效的,因此,這筆交易也就無(wú)法被加到區(qū)塊鏈中。
我們現(xiàn)在離實(shí)現(xiàn)交易簽名還差一件事情:用于簽名的數(shù)據(jù)。一筆交易的哪些部分需要簽名?又或者說(shuō),要對(duì)完整的交易進(jìn)行簽名?選擇簽名的數(shù)據(jù)相當(dāng)重要。因?yàn)橛糜诤灻倪@個(gè)數(shù)據(jù),必須要包含能夠唯一識(shí)別數(shù)據(jù)的信息。比如,如果僅僅對(duì)輸出值進(jìn)行簽名并沒(méi)有什么意義,因?yàn)楹灻粫?huì)考慮發(fā)送方和接收方。
考慮到交易解鎖的是之前的輸出,然后重新分配里面的價(jià)值,并鎖定新的輸出,那么必須要簽名以下數(shù)據(jù):
存儲(chǔ)在已解鎖輸出的公鑰哈希。它識(shí)別了一筆交易的發(fā)送方。存儲(chǔ)在新的鎖定輸出里面的公鑰哈希。它識(shí)別了一筆交易的接收方。新的輸出值。
在比特幣中,鎖定/解鎖邏輯被存儲(chǔ)在腳本中,它們被分別存儲(chǔ)在輸入和輸出的script_sig和script_pub_key字段。由于比特幣允許這樣不同類型的腳本,它對(duì)script_pub_key的整個(gè)內(nèi)容進(jìn)行了簽名。
可以看到,我們不需要對(duì)存儲(chǔ)在輸入里面的公鑰簽名。因此,在比特幣里,所簽名的并不是一個(gè)交易,而是一個(gè)去除部分內(nèi)容的輸入副本,輸入里面存儲(chǔ)了被引用輸出的script_pub_key。
獲取修剪后的交易副本的詳細(xì)過(guò)程在這里.雖然它可能已經(jīng)過(guò)時(shí)了,但是我并沒(méi)有找到另一個(gè)更可靠的來(lái)源。
看著有點(diǎn)復(fù)雜,來(lái)開(kāi)始寫代碼吧。先從sign方法開(kāi)始:
defsign(self,priv_key,prev_txs):
ifself.is_coinbase():
return
tx_copy=self._trimmed_copy()
forin_id,vininenumerate(tx_copy.vins):
prev_tx=prev_txs.get(vin.txid,None)
ifnotprev_tx:
raiseValueError('Previoustransactioniserror')
tx_copy.vins[in_id].signature=None
tx_copy.vins[in_id].pub_key=prev_tx.vouts[vin.vout].pub_key_hash
tx_copy.set_id()
tx_copy.vins[in_id].pub_key=None
sk=ecdsa.SigningKey.from_string(
binascii.a2b_hex(priv_key),curve=ecdsa.SECP256k1)
sign=sk.sign(tx_copy.txid.encode())
self.vins[in_id].signature=binascii.hexlify(sign).decode()
coinbase沒(méi)有輸入所以不需要簽名。
tx_copy=self._trimmed_copy()
將會(huì)被簽署的是修剪后的交易副本,而不是一個(gè)完整交易:
def_trimmed_copy(self):
inputs=[]
outputs=[]
forvininself.vins:
inputs.append(TXInput(vin.txid,vin.vout,None))
forvoutinself.vouts:
outputs.append(TXOutput(vout.value,vout.pub_key_hash))
tx=Transaction(inputs,outputs)
tx.txid=self.txid
returntx
接下來(lái),我們會(huì)迭代副本中每一個(gè)輸入:
forin_id,vininenumerate(tx_copy.vins):
prev_tx=prev_txs.get(vin.txid,None)
ifnotprev_tx:
raiseValueError('Previoustransactioniserror')
tx_copy.vins[in_id].signature=None
tx_copy.vins[in_id].pub_key=prev_tx.vouts[vin.vout].pub_key_hash
在每個(gè)輸入中,signature被設(shè)置為None(僅僅是一個(gè)雙重檢驗(yàn)),pub_key被設(shè)置為所引用輸出的pub_key_hash。現(xiàn)在,除了當(dāng)前交易,其他所有交易都是空的,也就是說(shuō)他們的signature和pub_key字段被設(shè)置為None。因此,輸入是被分開(kāi)簽名的,盡管這對(duì)于我們的應(yīng)用并不十分緊要,但是比特幣允許交易包含引用了不同地址的輸入。
tx_copy.set_id()
tx_copy.vins[in_id].pub_key=None
hash方法對(duì)交易進(jìn)行序列化,并使用SHA-256算法進(jìn)行哈希。哈希后的結(jié)果就是我們要簽名的數(shù)據(jù)。在獲取完哈希,我們應(yīng)該重置pub_key字段,以便于它不會(huì)影響后面的迭代。
現(xiàn)在,關(guān)鍵點(diǎn):
sk=ecdsa.SigningKey.from_string(
binascii.a2b_hex(priv_key),curve=ecdsa.SECP256k1)
sign=sk.sign(tx_copy.txid.encode())
self.vins[in_id].signature=binascii.hexlify(sign).decode()
我們通過(guò)priv_key對(duì)tx_copy.txid進(jìn)行簽名。一個(gè)ECDSA簽名就是一對(duì)數(shù)字,我們對(duì)這對(duì)數(shù)字連接起來(lái),并存儲(chǔ)在輸入的signature字段。
驗(yàn)證方法與簽名是類似的:
defverify(self,prev_txs):
tx_copy=self._trimmed_copy()
forin_id,vininenumerate(self.vins):
prev_tx=prev_txs.get(vin.txid,None)
ifnotprev_tx:
raiseValueError('Previoustransactioniserror')
tx_copy.vins[in_id].signature=None
tx_copy.vins[in_id].pub_key=prev_tx.vouts[vin.vout].pub_key_hash
tx_copy.set_id()
tx_copy.vins[in_id].pub_key=None
sign=binascii.unhexlify(self.vins[in_id].signature)
vk=ecdsa.VerifyingKey.from_string(
binascii.a2b_hex(vin.pub_key),curve=ecdsa.SECP256k1)
ifnotvk.verify(sign,tx_copy.txid.encode()):
returnFalse
returnTrue
和上面類似,先進(jìn)行副本的拷貝,然后置空signature,并重新計(jì)算id,然后再進(jìn)行校驗(yàn)
sign=binascii.unhexlify(self.vins[in_id].signature)
vk=ecdsa.VerifyingKey.from_string(
binascii.a2b_hex(vin.pub_key),curve=ecdsa.SECP256k1)
ifnotvk.verify(sign,tx_copy.txid.encode()):
returnFalse
如果校驗(yàn)失敗就直接返回False。
在new_transaction方法中加入簽名:
defnew_transaction(self,from_addr,to_addr,amount):
tx=Transaction(inputs,outputs)
tx.set_id()
self.sign_transaction(tx,from_wallet.private_key)
returntx
defmine(self,bc):
pow=ProofOfWork(self)
fortxinself._transactions:
ifnotbc.verify_transaction(tx):
raiseTransactionVerifyError('transactionverifyerror')
try:
nonce,_=pow.run()
exceptNonceNotFoundErrorase:
print(e)
self._block_header.nonce=nonce
在挖礦方法mine加入交易參數(shù)校驗(yàn)。
測(cè)試:
$python3cli.pycreatewallet
Yournewaddressis11oHh3J3jx4yjKppGjCXijVxxc6QZU8zr
$python3cli.pyprintwallet
Walletare:
LZTnHqJG4sSHXHY5Yx1gDqXv9LKc1586Pj
#首先初始化
$python3mai
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 房屋建筑招標(biāo)合同
- 校園植樹(shù)協(xié)議書
- 運(yùn)動(dòng)面料采購(gòu)合同協(xié)議
- 配電元器件采購(gòu)合同協(xié)議
- 湖檔管護(hù)協(xié)議書
- 車輛合伙買賣合同協(xié)議
- 戰(zhàn)略合作協(xié)議發(fā)言稿
- 避免侵權(quán)協(xié)議書模板
- 服從外調(diào)協(xié)議書
- 服裝出兌協(xié)議書
- 美術(shù)高考集訓(xùn)班協(xié)議合同
- 中國(guó)證券經(jīng)營(yíng)行業(yè)市場(chǎng)發(fā)展現(xiàn)狀分析及發(fā)展趨勢(shì)與投資前景研究報(bào)告
- 《肺結(jié)核的診斷與治療》課件
- 陜西省咸陽(yáng)市2025屆高三下學(xué)期高考模擬檢測(cè)(三)物理試題(含答案)
- 浙江省溫州市2023-2024學(xué)年高一下學(xué)期期末考試語(yǔ)文試卷(含答案)
- GB 38031-2025電動(dòng)汽車用動(dòng)力蓄電池安全要求
- (高清版)DB3301∕T 0411-2023 公共汽電車維修車間建設(shè)與管理規(guī)范
- 水果店運(yùn)營(yíng)與管理培訓(xùn)課件
- 1號(hào)卷·A10聯(lián)盟2025屆高三4月質(zhì)檢考物理試題及答案
- 激光應(yīng)用技術(shù)發(fā)展路徑試題及答案
- 2025年一級(jí)建造師之一建礦業(yè)工程實(shí)務(wù)題庫(kù)附答案(典型題)
評(píng)論
0/150
提交評(píng)論