-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbcp_nft_v2.go
78 lines (67 loc) · 2.93 KB
/
bcp_nft_v2.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package script
import (
"encoding/binary"
)
// nft
func decodeNFT(scriptLen int, pkScript []byte, txo *TxoData) bool {
dataLen := 0
protoVersionLen := 0
genesisIdLen := 76 // nft v2
sensibleIdLen := 36
useTokenIdHash := false
if pkScript[scriptLen-89-76-1-1-1] == OP_RETURN &&
pkScript[scriptLen-89-76-1-1] == 0x4c &&
pkScript[scriptLen-89-76-1] == 165 {
// nft v3
// <nft data> = <metaid_outpoint(36 bytes)> + <is_genesis(1 byte)> + <address(20 bytes)> + <totalSupply(8 bytes) + <tokenIndex(8 bytes)> + <genesisHash<20 bytes>) + <RABIN_PUBKEY_HASH_ARRAY_HASH(20 bytes)> + <sensibleID(36 bytes)> + <protoVersion(4 bytes)> + <protoType(4 bytes)> + <protoFlag(8 bytes)>
dataLen = 1 + 1 + 36 + 1 + 20 + 8 + 8 + 20 + 20 + 36 + 4 + 4 + 8 // 0x4c + pushdata + data
protoVersionLen = 4
useTokenIdHash = true
} else if pkScript[scriptLen-85-76-1-1-1] == OP_RETURN &&
pkScript[scriptLen-85-76-1-1] == 0x4c &&
pkScript[scriptLen-85-76-1] == 161 {
// nft v2
// <nft data> = <metaid_outpoint(36 bytes)> + <is_genesis(1 byte)> + <address(20 bytes)> + <totalSupply(8 bytes) + <tokenIndex(8 bytes)> + <genesisHash<20 bytes>) + <RABIN_PUBKEY_HASH_ARRAY_HASH(20 bytes)> + <sensibleID(36 bytes)> + <protoType(4 bytes)> + <protoFlag(8 bytes)>
dataLen = 1 + 1 + 1 + 36 + 1 + 20 + 8 + 8 + 20 + 20 + 36 + 4 + 8 // opreturn + 0x4c + pushdata + data
protoVersionLen = 0
useTokenIdHash = false
} else {
return false
}
protoTypeOffset := scriptLen - 8 - 4
sensibleOffset := protoTypeOffset - protoVersionLen - sensibleIdLen
genesisOffset := protoTypeOffset - protoVersionLen - genesisIdLen
tokenIndexOffset := genesisOffset - 8
tokenSupplyOffset := tokenIndexOffset - 8
addressOffset := tokenSupplyOffset - 20
isGenesisOffset := addressOffset - 1
metaOutputIndexOffset := isGenesisOffset - 4
metaTxIdOffset := metaOutputIndexOffset - 32
txo.CodeType = CodeType_NFT
nft := &NFTData{
SensibleId: make([]byte, sensibleIdLen),
TokenSupply: binary.LittleEndian.Uint64(pkScript[tokenSupplyOffset : tokenSupplyOffset+8]),
TokenIndex: binary.LittleEndian.Uint64(pkScript[tokenIndexOffset : tokenIndexOffset+8]),
}
txo.NFT = nft
copy(txo.CodeHash[:], GetHash160(pkScript[:scriptLen-dataLen]))
copy(nft.SensibleId, pkScript[sensibleOffset:sensibleOffset+sensibleIdLen])
if useTokenIdHash {
// GenesisId is tokenIdHash
txo.GenesisIdLen = 20
copy(txo.GenesisId[:], GetHash160(pkScript[genesisOffset:genesisOffset+genesisIdLen]))
} else {
// for search: codehash + genesis
txo.GenesisIdLen = uint8(sensibleIdLen)
copy(txo.GenesisId[:], nft.SensibleId)
}
nft.MetaOutputIndex = binary.LittleEndian.Uint32(pkScript[metaOutputIndexOffset : metaOutputIndexOffset+4])
copy(nft.MetaTxId[:], pkScript[metaTxIdOffset:metaTxIdOffset+32])
ReverseBytesInPlace(nft.MetaTxId[:])
if pkScript[isGenesisOffset] == 1 {
nft.TokenIndex = nft.TokenSupply
}
txo.HasAddress = true
copy(txo.AddressPkh[:], pkScript[addressOffset:addressOffset+20])
return true
}