uint32_t CBTransactionOutputCalculateLength(CBTransactionOutput * self){ if (CBGetMessage(self)->serialised) { // If it is serailised, the var int may be of a different size. uint8_t byte = CBByteArrayGetByte(CBGetMessage(self)->bytes, 0); return (byte < 253 ? 1 : (byte == 253 ? 3 : (byte == 254 ? 5 : 9))) + self->scriptObject->length + 8; } else return CBVarIntSizeOf(self->scriptObject->length) + self->scriptObject->length + 8; }
uint8_t CBNetworkAddressSerialise(CBNetworkAddress * self, bool timestamp){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (! bytes) { CBLogError("Attempting to serialise a CBNetworkAddress with no bytes."); return 0; } if (bytes->length < 26 + timestamp * 4) { CBLogError("Attempting to serialise a CBNetworkAddress with less bytes than required."); return 0; } uint8_t cursor; if (timestamp) { CBByteArraySetInt32(bytes, 0, (uint32_t)(self->lastSeen - self->penalty)); cursor = 4; }else cursor = 0; CBByteArraySetInt64(bytes, cursor, self->services); cursor += 8; CBByteArrayCopyByteArray(bytes, cursor, self->ip); CBByteArrayChangeReference(self->ip, bytes, cursor); cursor += 16; CBByteArraySetPort(bytes, cursor, self->port); bytes->length = cursor + 2; CBGetMessage(self)->serialised = true; return cursor + 2; }
int CBAlertSerialiseSignature(CBAlert * self, int offset) { CBByteArray * bytes = CBGetMessage(self)->bytes; if (! bytes) { CBLogError("Attempting to serialise a CBAlert with no bytes."); return 0; } CBVarInt sigLen = CBVarIntFromUInt64(self->signature->length); if (bytes->length < offset + sigLen.size + sigLen.val) { CBLogError("Attempting to serialise a CBAlert with less bytes than required for the signature."); return 0; } CBByteArraySetVarInt(bytes, offset, sigLen); offset += sigLen.size; CBByteArrayCopyByteArray(bytes, offset, self->signature); CBByteArrayChangeReference(self->signature, bytes, offset); bytes->length = offset + (int)sigLen.val; CBGetMessage(self)->serialised = true; return bytes->length; }
uint32_t CBTransactionOutputSerialise(CBTransactionOutput * self){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (NOT bytes) { CBLogError("Attempting to serialise a CBTransactionInput with no bytes."); return 0; } if (NOT self->scriptObject){ CBLogError("Attempting to serialise a CBTransactionOutput without scriptObject."); return 0; } CBVarInt scriptLen = CBVarIntFromUInt64(CBGetByteArray(self->scriptObject)->length); uint32_t reqLen = 8 + scriptLen.size + CBGetByteArray(self->scriptObject)->length; if (bytes->length < reqLen) { CBLogError("Attempting to serialise a CBTransactionOutput with less bytes than required. %i < %i", bytes->length, reqLen); return 0; } // Serialise data into the CBByteArray and rereference objects to this CBByteArray to save memory. CBByteArraySetInt64(bytes, 0, self->value); CBVarIntEncode(bytes, 8, scriptLen); CBByteArrayCopyByteArray(bytes, 8 + scriptLen.size, CBGetByteArray(self->scriptObject)); CBByteArrayChangeReference(CBGetByteArray(self->scriptObject), bytes, 8 + scriptLen.size); // Ensure length is correct bytes->length = reqLen; // Is serialised. CBGetMessage(self)->serialised = true; return reqLen; }
uint32_t CBAddressBroadcastDeserialise(CBAddressBroadcast * self){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (NOT bytes) { CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_NULL_BYTES,"Attempting to deserialise a CBAddressBroadcast with no bytes."); return 0; } if (bytes->length < 26 + self->timeStamps * 4) { CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_BAD_BYTES,"Attempting to deserialise a CBAddressBroadcast without enough bytes to cover one address."); return 0; } CBVarInt num = CBVarIntDecode(bytes, 0); if (num.val > 30) { CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_BAD_BYTES,"Attempting to deserialise a CBAddressBroadcast with a var int over 30."); return 0; } self->addresses = malloc(sizeof(*self->addresses) * (size_t)num.val); if (NOT self->addresses) { CBGetMessage(self)->onErrorReceived(CB_ERROR_OUT_OF_MEMORY,"Cannot allocate %i bytes of memory in CBAddressBroadcastDeserialise\n",sizeof(*self->addresses) * (size_t)num.val); return 0; } self->addrNum = num.val; uint16_t cursor = num.size; for (uint8_t x = 0; x < num.val; x++) { // Make new CBNetworkAddress from the rest of the data. uint8_t len; CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor); if (data) { self->addresses[x] = CBNewNetworkAddressFromData(data, CBGetMessage(self)->onErrorReceived); if (self->addresses[x]){ // Deserialise len = CBNetworkAddressDeserialise(self->addresses[x], self->timeStamps); if (NOT len) CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_BAD_BYTES,"CBAddressBroadcast cannot be deserialised because of an error with the CBNetworkAddress number %u.",x); }else{ len = 0; CBGetMessage(self)->onErrorReceived(CB_ERROR_INIT_FAIL,"Could not create CBNetworkAddress in CBAddressBroadcastDeserialise for network address %u.",x); } }else{ len = 0; CBGetMessage(self)->onErrorReceived(CB_ERROR_INIT_FAIL,"Could not create CBByteArray in CBAddressBroadcastDeserialise for network address %u.",x); } if (NOT len) { // Release bytes CBReleaseObject(data); return 0; } // Adjust length data->length = len; CBReleaseObject(data); cursor += len; } return cursor; }
bool CBInitNetworkAddressFromData(CBNetworkAddress * self, CBByteArray * data, bool isPublic){ self->ip = NULL; self->bucketSet = false; if (NOT CBInitMessageByData(CBGetMessage(self), data)) return false; return true; }
bool CBInitNetworkAddress(CBNetworkAddress * self, uint64_t lastSeen, CBByteArray * ip, uint16_t port, CBVersionServices services, bool isPublic){ self->lastSeen = lastSeen; self->penalty = 0; self->ip = ip; self->isPublic = isPublic; if (NOT ip) { ip = CBNewByteArrayOfSize(16); if (NOT ip) return false; memset(CBByteArrayGetData(ip), 0, 16); self->type = CB_IP_INVALID; }else{ // Determine IP type self->type = CBGetIPType(CBByteArrayGetData(ip)); CBRetainObject(ip); } self->port = port; self->services = services; self->bucketSet = false; if (NOT CBInitMessageByObject(CBGetMessage(self))){ CBReleaseObject(ip); return false; } return true; }
bool CBInitInventoryBroadcastFromData(CBInventoryBroadcast * self,CBByteArray * data,CBEvents * events){ self->itemNum = 0; self->items = NULL; if (NOT CBInitMessageByData(CBGetMessage(self), data, events)) return false; return true; }
void CBInitInventoryFromData(CBInventory * self, CBByteArray * data) { self->itemNum = 0; self->itemFront = NULL; CBInitMessageByData(CBGetMessage(self), data); }
bool CBInitBlockHeadersFromData(CBBlockHeaders * self,CBByteArray * data,void (*logError)(char *,...)) { self->headerNum = 0; self->blockHeaders = NULL; if (NOT CBInitMessageByData(CBGetMessage(self), data, logError)) return false; return true; }
uint32_t CBTransactionInputDeserialise(CBTransactionInput * self){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (! bytes) { CBLogError("Attempting to deserialise a CBTransactionInput with no bytes."); return 0; } if (bytes->length < 41) { CBLogError("Attempting to deserialise a CBTransactionInput with less than 41 bytes."); return 0; } CBVarInt scriptLen = CBVarIntDecode(bytes, 36); if (scriptLen.val > 10000) { CBLogError("Attempting to deserialise a CBTransactionInput with too big a script."); return 0; } uint32_t reqLen = (uint32_t)(40 + scriptLen.size + scriptLen.val); if (bytes->length < reqLen) { CBLogError("Attempting to deserialise a CBTransactionInput with less bytes than needed according to the length for the script. %i < %i", bytes->length, reqLen); return 0; } // Deserialise by subreferencing byte arrays and reading integers. self->prevOut.hash = CBByteArraySubReference(bytes, 0, 32); self->prevOut.index = CBByteArrayReadInt32(bytes, 32); self->scriptObject = CBNewScriptFromReference(bytes, 36 + scriptLen.size, (uint32_t) scriptLen.val); self->sequence = CBByteArrayReadInt32(bytes, (uint32_t) (36 + scriptLen.size + scriptLen.val)); return reqLen; }
bool CBInitBlockHeaders(CBBlockHeaders * self) { self->headerNum = 0; self->blockHeaders = NULL; if (NOT CBInitMessageByObject(CBGetMessage(self))) return false; return true; }
bool CBInitChainDescriptorFromData(CBChainDescriptor * self,CBByteArray * data,void (*logError)(char *,...)){ self->hashNum = 0; self->hashes = NULL; if (NOT CBInitMessageByData(CBGetMessage(self), data, logError)) return false; return true; }
bool CBInitChainDescriptor(CBChainDescriptor * self,void (*logError)(char *,...)){ self->hashNum = 0; self->hashes = NULL; if (NOT CBInitMessageByObject(CBGetMessage(self), logError)) return false; return true; }
bool CBInitTransactionInputFromData(CBTransactionInput * self, CBByteArray * data,void (*onErrorReceived)(CBError error,char *,...)){ self->scriptObject = NULL; self->prevOut.hash = NULL; if (NOT CBInitMessageByData(CBGetMessage(self), data, onErrorReceived)) return false; return true; }
bool CBInitInventoryBroadcastFromData(CBInventoryBroadcast * self,CBByteArray * data,void (*onErrorReceived)(CBError error,char *,...)){ self->itemNum = 0; self->items = NULL; if (NOT CBInitMessageByData(CBGetMessage(self), data, onErrorReceived)) return false; return true; }
bool CBInitInventoryBroadcast(CBInventoryBroadcast * self,void (*onErrorReceived)(CBError error,char *,...)){ self->itemNum = 0; self->items = NULL; if (NOT CBInitMessageByObject(CBGetMessage(self), onErrorReceived)) return false; return true; }
uint16_t CBChainDescriptorDeserialise(CBChainDescriptor * self){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (! bytes) { CBLogError("Attempting to deserialise a CBChainDescriptor with no bytes."); return 0; } if (bytes->length < 1) { CBLogError("Attempting to deserialise a CBChainDescriptor with no bytes"); return 0; } CBVarInt hashNum = CBVarIntDecode(bytes, 0); if (hashNum.val > 500) { CBLogError("Attempting to deserialise a CBChainDescriptor with a var int over 500."); return 0; } if (bytes->length < hashNum.size + hashNum.val * 32) { CBLogError("Attempting to deserialise a CBChainDescriptor with less bytes than required for the hashes."); return 0; } // Deserialise each hash self->hashes = malloc(sizeof(*self->hashes) * (size_t)hashNum.val); self->hashNum = hashNum.val; uint16_t cursor = hashNum.size; for (uint16_t x = 0; x < self->hashNum; x++) { self->hashes[x] = CBNewByteArraySubReference(bytes, cursor, 32); cursor += 32; } return cursor; }
void CBInitTransactionInputTakeScriptAndHash(CBTransactionInput * self, CBScript * script, uint32_t sequence, CBByteArray * prevOutHash, uint32_t prevOutIndex){ self->scriptObject = script; self->prevOut.hash = prevOutHash; self->prevOut.index = prevOutIndex; self->sequence = sequence; CBInitMessageByObject(CBGetMessage(self)); }
bool CBInitBlockHeadersFromData(CBBlockHeaders * self, CBByteArray * data) { self->headerNum = 0; self->blockHeaders = NULL; if (NOT CBInitMessageByData(CBGetMessage(self), data)) return false; return true; }
bool CBInitBlockHeaders(CBBlockHeaders * self,void (*logError)(char *,...)) { self->headerNum = 0; self->blockHeaders = NULL; if (NOT CBInitMessageByObject(CBGetMessage(self), logError)) return false; return true; }
uint8_t CBNetworkAddressDeserialise(CBNetworkAddress * self, bool timestamp){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (! bytes) { CBLogError("Attempting to deserialise a CBNetworkAddress with no bytes."); return 0; } if (bytes->length < 26 + timestamp * 4) { CBLogError("Attempting to deserialise a CBNetworkAddress with less bytes than required."); return 0; } uint8_t start; uint64_t twoHoursAgo = time(NULL) - 3600; if (timestamp) { // Make sure we do not set self->lastSeen later than one hour ago. self->lastSeen = CBByteArrayReadInt32(bytes, 0); if (self->lastSeen > twoHoursAgo) self->lastSeen = twoHoursAgo; start = 4; }else{ self->lastSeen = twoHoursAgo; start = 0; } self->services = (CBVersionServices) CBByteArrayReadInt64(bytes, start); self->ip = CBNewByteArraySubReference(bytes, start + 8, 16); // Determine IP type self->type = CBGetIPType(CBByteArrayGetData(self->ip)); self->port = CBByteArrayReadPort(bytes, start + 24); return start + 26; }
uint32_t CBInventoryItemSerialise(CBInventoryItem * self){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (NOT bytes) { CBGetMessage(self)->logError("Attempting to serialise a CBInventoryItem with no bytes."); return 0; } if (bytes->length < 36) { CBGetMessage(self)->logError("Attempting to serialise a CBInventoryItem with less than 36 bytes."); return 0; } CBByteArraySetInt32(bytes, 0, self->type); CBByteArrayCopyByteArray(bytes, 4, self->hash); CBByteArrayChangeReference(self->hash, bytes, 4); CBGetMessage(self)->serialised = true; return 36; }
void CBInitInventory(CBInventory * self) { self->itemNum = 0; self->itemFront = NULL; CBInitMessageByObject(CBGetMessage(self)); }
uint32_t CBInventoryItemDeserialise(CBInventoryItem * self){ CBByteArray * bytes = CBGetMessage(self)->bytes; if (NOT bytes) { CBGetMessage(self)->logError("Attempting to deserialise a CBInventoryItem with no bytes."); return 0; } if (bytes->length < 36) { CBGetMessage(self)->logError("Attempting to deserialise a CBInventoryItem with less than 36 bytes."); return 0; } self->type = CBByteArrayReadInt32(bytes, 0); self->hash = CBByteArraySubReference(bytes, 4, 32); if (NOT self->hash) return 0; return 36; }
bool CBInitInventoryBroadcast(CBInventoryBroadcast * self,CBEvents * events){ self->itemNum = 0; self->items = NULL; if (NOT CBInitMessageByObject(CBGetMessage(self), events)) return false; return true; }
void CBInitAlert(CBAlert * self, int32_t version, int64_t relayUntil, int64_t expiration, int32_t ID, int32_t cancel, int32_t minVer, int32_t maxVer, int32_t priority, CBByteArray * hiddenComment, CBByteArray * displayedComment, CBByteArray * reserved) { self->version = version; self->relayUntil = relayUntil; self->expiration = expiration; self->ID = ID; self->cancel = cancel; self->minVer = minVer; self->maxVer = maxVer; self->priority = priority; self->hiddenComment = hiddenComment; if (hiddenComment) CBRetainObject(hiddenComment); self->displayedComment = displayedComment; if (displayedComment) CBRetainObject(displayedComment); self->reserved = reserved; if (reserved) CBRetainObject(reserved); self->signature = NULL; self->payload = NULL; CBInitMessageByObject(CBGetMessage(self)); }
bool CBInitVersionFromData(CBVersion * self,CBByteArray * data,void (*logError)(char *,...)){ self->addRecv = NULL; self->userAgent = NULL; self->addSource = NULL; if (NOT CBInitMessageByData(CBGetMessage(self), data, logError)) return false; return true; }
CBByteArray * CBAlertGetPayload(CBAlert * self) { CBByteArray * bytes = CBGetMessage(self)->bytes; CBVarInt payloadLen = CBByteArrayReadVarInt(bytes, 0); return CBNewByteArraySubReference(bytes, payloadLen.size, (int)payloadLen.val); }
bool CBInitInventoryItem(CBInventoryItem * self,CBInventoryItemType type,CBByteArray * hash,void (*logError)(char *,...)){ self->type = type; self->hash = hash; CBRetainObject(hash); if (NOT CBInitMessageByObject(CBGetMessage(self), logError)) return false; return true; }