<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ayush Agrawal's Blog]]></title><description><![CDATA[Ayush Agrawal's Blog]]></description><link>https://blog.ayushagr.me</link><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 01:11:02 GMT</lastBuildDate><atom:link href="https://blog.ayushagr.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The 7 Bytes That Weren't in the IDL: How #[repr(C)] Padding Breaks a Borsh Client]]></title><description><![CDATA[A single u64 added seven bytes of padding the compiler knew about and the client didn't. Here is why, and how to predict it for any #[repr(C)] struct.
The failure
I added one field to an instruction-a]]></description><link>https://blog.ayushagr.me/the-7-bytes-that-weren-t-in-the-idl-how-repr-c-padding-breaks-a-borsh-client</link><guid isPermaLink="true">https://blog.ayushagr.me/the-7-bytes-that-weren-t-in-the-idl-how-repr-c-padding-breaks-a-borsh-client</guid><category><![CDATA[Rust]]></category><category><![CDATA[Solana]]></category><category><![CDATA[pinocchio]]></category><category><![CDATA[borsh]]></category><category><![CDATA[zero-copy]]></category><category><![CDATA[repr(C)]]></category><category><![CDATA[memory layout]]></category><category><![CDATA[struct-padding]]></category><category><![CDATA[alignment]]></category><category><![CDATA[idl]]></category><category><![CDATA[on-chain-programs]]></category><category><![CDATA[Systems Programming]]></category><dc:creator><![CDATA[Ayush Agrawal]]></dc:creator><pubDate>Wed, 15 Jul 2026 17:54:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/601c00e01054fa16dadd5fd8/52d82ddb-8edb-4943-b525-ef2b3ca8aaaf.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A single <code>u64</code> added seven bytes of padding the compiler knew about and the client didn't. Here is why, and how to predict it for any <code>#[repr(C)]</code> struct.</p>
<h2>The failure</h2>
<p>I added one field to an instruction-args struct, a plain <code>u64</code>, and my generated client stopped working. Same logical arguments as before (an owner, an amount, a bump), correct values, correct order. The program rejected it anyway. When I built the exact same instruction by hand, it went through.</p>
<p>Here is what that looked like against the program, verbatim from my own debugging run:</p>
<pre><code class="language-text">[1] client-built ix: 41 arg bytes (borsh). Program expects size_of::&lt;Initialize&gt;() = 48.
    Transaction simulation failed: Error processing Instruction 0: custom program error: 0x0
  Program CbMX... invoke [1]
  Program log: initialize
  Program CbMX... failed: custom program error: 0x0
 
[2] hand-built repr(C) ix: 48 arg bytes.
    SUCCESS
</code></pre>
<p>Forty-one bytes rejected. Forty-eight bytes accepted. The difference is not the data. It is seven bytes that exist in the program's view of the struct and do not exist in the client's. Those seven bytes are trailing padding, and nothing in the generated IDL told the client to send them.</p>
<p>This post is the walk from that <code>custom program error: 0x0</code> back to the layout rule that explains it, so that next time you can predict the padding before it costs you a debugging session.</p>
<h2>TL;DR</h2>
<ul>
<li><p>A zero-copy read (<code>&amp;*(ptr as *const T)</code>) requires the exact <code>#[repr(C)]</code> byte layout, which includes any padding, so it demands <code>size_of::&lt;T&gt;()</code> bytes.</p>
</li>
<li><p>A borsh client serializes fields packed, with no padding, so it sends <code>Σ field sizes</code> bytes.</p>
</li>
<li><p>They agree only when the struct has no implicit padding, that is, when <code>size_of::&lt;T&gt;() == Σ field sizes</code>.</p>
</li>
<li><p>Padding is a function of field alignments, field order, and total size. It is not caused by "having a big field" on its own.</p>
</li>
<li><p>The reliable fixes: use only align-1 fields, or order fields by descending alignment, or expose the gap as an explicit <code>_padding: [u8; N]</code> field so it appears in the IDL and the client sends it too.</p>
</li>
<li><p>Verify with <code>size_of::&lt;T&gt;() == Σ field sizes</code>. A compile-time <code>assert!</code> on that catches the regression at build time.</p>
</li>
</ul>
<h2>Why this bites: two layouts that must agree</h2>
<p>On Solana, an on-chain program and its off-chain client are two programs that have to agree on a byte buffer. In a pinocchio-style program, instruction arguments are read <em>zero-copy</em>: the program takes the raw instruction-data bytes and casts a pointer straight to your struct, no deserialization step. The general technique is what pinocchio is built around. As <a href="https://www.anza.xyz/blog/febo-on-pinocchio-p-token-and-pushing-solanas-limits">an article from Anza</a> (by Febo, a core engineer at Anza) puts it, zero-copy means reading data straight from the input buffer instead of deserializing it into owned types, which for fixed-layout data avoids a large amount of unnecessary work. That cast only produces correct fields if the incoming bytes are laid out exactly as the compiler laid out the struct, which means the full <code>#[repr(C)]</code> layout, padding and all. A zero-copy read of <code>T</code> wants <code>size_of::&lt;T&gt;()</code> bytes, in <code>T</code>'s exact in-memory shape.</p>
<p>The generated client, on the other hand, serializes the same arguments with borsh. Borsh packs fields back to back with no padding. So the client emits <code>Σ field sizes</code> bytes.</p>
<p>Those two numbers are equal only when the struct carries no implicit padding. When they differ, the client and the program disagree about how many bytes the arguments are, and the arguments are read wrong or, as above, rejected outright. Everything else in this post is about predicting that one equality.</p>
<h2>Size and alignment: the two numbers</h2>
<p>Every type in Rust has two numbers that drive layout:</p>
<ul>
<li><p><strong>size</strong>: how many bytes it occupies.</p>
</li>
<li><p><strong>alignment</strong>: a value of this type must start at an offset that is a multiple of this number. Padding exists for exactly one reason: to satisfy alignment. If nothing needed to start on a boundary, nothing would ever be padded.</p>
</li>
</ul>
<h2>Alignment of the types you actually use</h2>
<p>The layout algorithm below runs on the alignments of the primitives you build with, so here they are. The one that trips people is at the bottom: a 32-byte pubkey is align 1, not align 32, because it is a byte array.</p>
<table>
<thead>
<tr>
<th>Type</th>
<th>size</th>
<th>align</th>
</tr>
</thead>
<tbody><tr>
<td><code>bool</code>, <code>u8</code>, <code>i8</code></td>
<td>1</td>
<td><strong>1</strong></td>
</tr>
<tr>
<td><code>u16</code>, <code>i16</code></td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td><code>u32</code>, <code>i32</code>, <code>f32</code></td>
<td>4</td>
<td>4</td>
</tr>
<tr>
<td><code>u64</code>, <code>i64</code>, <code>f64</code></td>
<td>8</td>
<td>8</td>
</tr>
<tr>
<td><code>u128</code>, <code>i128</code></td>
<td>16</td>
<td>16</td>
</tr>
<tr>
<td><code>[T; N]</code></td>
<td>N × size(T)</td>
<td>align(T)</td>
</tr>
<tr>
<td><code>Address</code> / <code>Pubkey</code> (<code>[u8; 32]</code> newtype)</td>
<td>32</td>
<td><strong>1</strong></td>
</tr>
<tr>
<td>a struct</td>
<td>(see below)</td>
<td>max alignment of its fields</td>
</tr>
</tbody></table>
<p><code>Address</code> and <code>Pubkey</code> are byte arrays: align 1, size 32. They never cause padding on their own, which is why an all-pubkey struct is always safe to read zero-copy.</p>
<h2>The <code>#[repr(C)]</code> layout algorithm</h2>
<p><code>#[repr(C)]</code> gives you a defined, predictable layout (unlike the default <code>repr(Rust)</code>, which the compiler may reorder). The whole thing is this loop:</p>
<pre><code class="language-text">offset = 0
for each field, in declaration order:
    offset = round_up(offset, align(field))   # gap here = INTERNAL padding
    place field at offset
    offset += size(field)
 
struct_align = max(align(field) for all fields)
struct_size  = round_up(offset, struct_align) # gap here = TRAILING padding
</code></pre>
<p><code>round_up(x, a)</code> is the smallest multiple of <code>a</code> that is <code>&gt;= x</code>.</p>
<p>Three consequences fall directly out of this, and they are the load-bearing facts for the rest of the post:</p>
<ul>
<li><p><code>size_of::&lt;T&gt;()</code> equals <code>struct_size</code>, which includes all padding.</p>
</li>
<li><p>The borsh size equals the sum of the field sizes, with no padding.</p>
</li>
<li><p>Therefore <strong>implicit padding is present if and only if</strong> <code>size_of::&lt;T&gt;() != Σ field sizes</code><strong>.</strong> That last line is the entire test. If those two numbers match, the client and the program agree. If they do not, they do not.</p>
</li>
</ul>
<h2>Two kinds of padding: internal and trailing</h2>
<p>The algorithm inserts padding in two places, and they have different fixes, so it is worth naming them.</p>
<p><strong>Internal padding</strong> sits between fields. A field whose alignment is greater than 1 lands on an offset that is not a multiple of its alignment, so the compiler inserts bytes before it:</p>
<pre><code class="language-text">struct { a: u8, b: u64 }
 offset 0: a            (1 byte)
 offset 1..8: PAD       (7 bytes; u64 needs offset % 8 == 0)
 offset 8: b            (8 bytes)
 size = 16, sum = 9   -&gt; 7 bytes internal padding
</code></pre>
<p><strong>Trailing padding</strong> sits at the end. The final size is not a multiple of the struct's own alignment, so bytes are appended, so that an array of the struct keeps every element aligned:</p>
<pre><code class="language-text">struct { a: u64, b: u8 }
 offset 0: a            (8 bytes)
 offset 8: b            (1 byte)  -&gt; offset now 9
 struct_align = 8, round_up(9, 8) = 16
 size = 16, sum = 9   -&gt; 7 bytes trailing padding
</code></pre>
<p>Notice the same two fields, in either order, still cost 7 bytes of padding. Reordering moved <em>where</em> the padding lands (internal vs trailing) but not <em>whether</em> it exists. That is a useful warning: field ordering is a real tool, but it is not a guaranteed fix by itself.</p>
<h2>When padding appears: the rules</h2>
<p>Three cases cover every struct, and you can sort any struct into one without running the compiler.</p>
<p><strong>No padding, guaranteed:</strong> every field has align 1 (<code>u8</code>, <code>i8</code>, <code>bool</code>, <code>[u8; N]</code>, <code>Address</code>, <code>Pubkey</code>), in any order. Nothing ever needs a boundary, so nothing is ever inserted.</p>
<p><strong>No padding, if you are careful:</strong> fields are placed so each aligned field lands on its boundary with no gap, and the total size is already a multiple of the largest alignment. In practice that means order fields by descending alignment (which removes internal padding), and arrange for the running total to reach a multiple of the biggest alignment on its own, or add an explicit <code>_padding</code> field to reach it (which removes trailing padding).</p>
<p><strong>Padding appears when</strong> either a field with align &gt; 1 follows fields whose sizes do not add up to a multiple of that field's alignment (internal padding), or the total size is not a multiple of the struct's max alignment (trailing padding).</p>
<p>So padding is a function of field alignments, order, and total size, not of "having a big field." A <code>u64</code> alone in a struct pads nothing (<code>{ u64 }</code> is size 8). A <code>u64</code> sitting next to a <code>u8</code> is what introduces the gap.</p>
<h2>A gallery of worked examples</h2>
<p>Here is the rule applied across a spread of structs. Two of these are marked because they show up later: the safe all-align-1 case, and the one that actually broke.</p>
<pre><code class="language-text">{ u8 }                       size 1,  sum 1    no padding
{ u64 }                      size 8,  sum 8    no padding
{ u32, u32 }                 size 8,  sum 8    no padding
{ u32, u16, u16 }            size 8,  sum 8    no padding
{ u16, u16, u32 }            size 8,  sum 8    no padding
{ Address, u8 }              size 33, sum 33   no padding   (both align 1)
{ u8, u64 }                  size 16, sum 9    7 internal
{ u64, u8 }                  size 16, sum 9    7 trailing
{ u16, u32 }                 size 8,  sum 6    2 internal
{ u32, u16 }                 size 8,  sum 6    2 trailing
{ Address, u64, u8 }         size 48, sum 41   7 trailing   &lt;- the bug below
{ u8, u32, u8 }              size 12, sum 6    (3 before u32) + (3 trailing) = 6
{ u128, u8 }                 size 32, sum 17   15 trailing
</code></pre>
<p>That <code>{ Address, u64, u8 }</code> line, size 48, sum 41, seven bytes of trailing padding, is the struct that produced the <code>custom program error: 0x0</code>.</p>
<h2>Back to the bug</h2>
<p>The struct started as a scaffold instruction-args type. I added the <code>amount: u64</code> in the middle:</p>
<pre><code class="language-rust">#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, shank::ShankType)]
pub struct Initialize {
    pub owner: Address,   // 32
    pub amount: u64,      // 8   &lt;- added this
    pub bump: u8,         // 1
}
</code></pre>
<p>Adding the <code>u64</code> raised the struct's alignment to 8. Now walk the layout:</p>
<table>
<thead>
<tr>
<th>field</th>
<th>align</th>
<th>offset before</th>
<th>pad</th>
<th>at</th>
<th>after</th>
</tr>
</thead>
<tbody><tr>
<td><code>owner</code></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>32</td>
</tr>
<tr>
<td><code>amount</code></td>
<td>8</td>
<td>32</td>
<td>0 (32 is 8-aligned)</td>
<td>32</td>
<td>40</td>
</tr>
<tr>
<td><code>bump</code></td>
<td>1</td>
<td>40</td>
<td>0</td>
<td>40</td>
<td>41</td>
</tr>
<tr>
<td>end</td>
<td></td>
<td>41</td>
<td>struct align 8 -&gt; 41 rounds to 48</td>
<td></td>
<td>48</td>
</tr>
</tbody></table>
<p>So <code>size_of::&lt;Initialize&gt;()</code> is 48, while borsh is <code>32 + 8 + 1 = 41</code>. Seven bytes of trailing padding, exactly the amount needed to round 41 up to the next multiple of 8. The <code>owner</code> and <code>amount</code> fit perfectly (32 is already 8-aligned, so there is no <em>internal</em> padding); the whole cost lands at the tail.</p>
<p>The program reads the args zero-copy, and the read enforces the length:</p>
<pre><code class="language-rust">pub unsafe fn load_ix_data&lt;T&gt;(bytes: &amp;[u8]) -&gt; Result&lt;&amp;T, ProgramError&gt; {
    if bytes.len() != T::LEN {                 // T::LEN = size_of::&lt;Initialize&gt;() = 48
        return Err(MyProgramError::InvalidInstructionData.into());  // -&gt; custom error 0x0
    }
    Ok(&amp;*(bytes.as_ptr() as *const T))
}
</code></pre>
<p>The client sent 41 borsh bytes. <code>41 != 48</code>, so the guard returns <code>InvalidInstructionData</code>, which surfaces as <code>custom program error: 0x0</code>. The seven padding bytes are the whole problem: they are not in the IDL, so the client never serialized them.</p>
<p>One nuance worth keeping, because it tells you <em>where</em> padding bites. The account (state) struct in the same program, holding just <code>owner: Address</code> and <code>amount: u64</code>, is size 40 and borsh 40, padding-free, so its account path round-trips fine. Both the args struct and the account struct are read on-chain by the same family of raw-pointer cast; the account struct simply happens to have no padding, so its borsh client agrees. Padding broke the instruction-args struct, not the account struct, and it was the layout of the struct that decided it, not the read mechanism.</p>
<h2>The fix, and the guards</h2>
<p>The fix is to stop hiding the padding. Turn those seven trailing bytes into a real field:</p>
<pre><code class="language-rust">#[repr(C)]
pub struct Initialize {
    pub owner: Address,     // 32
    pub amount: u64,        // 8
    pub bump: u8,           // 1
    pub _padding: [u8; 7],  // 7   &lt;- explicit; now a real field, and in the IDL
}
</code></pre>
<table>
<thead>
<tr>
<th>field</th>
<th>align</th>
<th>at</th>
<th>after</th>
</tr>
</thead>
<tbody><tr>
<td><code>owner</code></td>
<td>1</td>
<td>0</td>
<td>32</td>
</tr>
<tr>
<td><code>amount</code></td>
<td>8</td>
<td>32</td>
<td>40</td>
</tr>
<tr>
<td><code>bump</code></td>
<td>1</td>
<td>40</td>
<td>41</td>
</tr>
<tr>
<td><code>_padding</code></td>
<td>1</td>
<td>41</td>
<td>48</td>
</tr>
<tr>
<td>end</td>
<td></td>
<td></td>
<td>48 (48 % 8 = 0, no trailing)</td>
</tr>
</tbody></table>
<p>Now <code>size_of</code> is 48 and the field sizes sum to <code>32 + 8 + 1 + 7 = 48</code>. Implicit padding is zero. Because <code>_padding</code> is a declared field, shank sees it, so it lands in the IDL, so the client serializes it too. The client now sends 48 bytes, exactly what <code>load_ix_data</code> expects. Both sides agree. Step <code>[2]</code> from the opening log already proved this shape works: a hand-built 48-byte payload (owner, amount, bump, then seven zero bytes) executed on-chain, and that is byte-for-byte what the client sends once <code>_padding: [u8; 7]</code> is a real field.</p>
<p>Because I would rather catch this at build time than in a simulation log, <code>pinoc</code> now ships two guards, and both are worth showing because they encode the rule directly.</p>
<p>The scaffold emits a compile-time assert next to the struct. On the plain scaffold struct (<code>Initialize { owner: Address, bump: u8 }</code>, size 33) it reads:</p>
<pre><code class="language-rust">const _: () = assert!(
    core::mem::size_of::&lt;Initialize&gt;() == 32 + 1,
    "Initialize has implicit padding; add explicit _padding fields so its #[repr(C)] layout matches the borsh client"
);
</code></pre>
<p>That <code>== 32 + 1</code> is the packed size the layout is supposed to have. The moment you add <code>amount: u64</code>, <code>size_of</code> becomes 48, the equality is now <code>48 == 33</code>, and the build fails at const-eval:</p>
<pre><code class="language-text">error[E0080]: evaluation panicked: Initialize has implicit padding; add explicit _padding fields so its #[repr(C)] layout matches the borsh client
  --&gt; src/instructions/initialize.rs:28:15
   |
28 |   const _: () = assert!(
   |  _______________^
29 | |     core::mem::size_of::&lt;Initialize&gt;() == 32 + 1,
30 | |     "Initialize has implicit padding; add explicit _padding fields so its #[repr(C)] layout matches the borsh client"
31 | | );
   | |_^ evaluation of `instructions::initialize::_` failed here
 
For more information about this error, try `rustc --explain E0080`.
error: could not compile `e0080_repro` (lib) due to 1 previous error
</code></pre>
<p>(The <code>error[E0080]: evaluation panicked: &lt;message&gt;</code> phrasing is toolchain-dependent; this is from the current Solana platform-tools rustc. Older compilers word const-assert failures differently, so pin your toolchain if you quote it. The crate name and line numbers above are from a scratch reproduction, not the committed template.)</p>
<p>For programs that do not carry the assert, <code>pinoc build</code> and <code>pinoc idl</code> run a lint that finds padded <code>#[repr(C)]</code> structs and prints:</p>
<pre><code class="language-text">⚠️  `Initialize` is #[repr(C)] with 7 byte(s) of implicit padding (layout size 48 vs packed 41). The generated client (de)serializes it as packed borsh, so it won't round-trip on-chain. Add explicit `_padding: [u8; 7]` field(s).
</code></pre>
<p>Both guards landed together and are on <code>main</code>. The source is public if you want to read the exact emitter and detection logic: <a href="https://github.com/A91y/pinoc">github.com/A91y/pinoc</a> (the assert lives in the scaffold templates, the lint in <code>src/idl/</code>, merged in commit <code>04031fb</code>).</p>
<p>One more note on explicit padding, because it is easy to over-learn the lesson. Explicit <code>_padding</code> is not always fixing an alignment problem. The Solana Foundation <code>pinocchio-counter</code> uses it on an all-align-1 struct:</p>
<pre><code class="language-rust">#[repr(C)]
struct Counter {
    bump: u8,
    _padding: [u8; 7],   // EXPLICIT padding: a real field, appears in the IDL
    authority: Address,  // 32
    count: u8,
}
</code></pre>
<p>Here <code>authority</code> is align 1, so nothing forces a gap. The <code>_padding</code> is a deliberate design choice, not an alignment repair. The underlying principle is the same either way: make every gap an explicit field so <code>size_of == Σ field sizes</code>, whether the gap is demanded by alignment or chosen by you.</p>
<h2>The checklist</h2>
<p>When you write a <code>#[repr(C)]</code> struct that will be read zero-copy on-chain and serialized by a borsh client:</p>
<ol>
<li><p><strong>Prefer align-1 fields.</strong> <code>u8</code>, <code>[u8; N]</code>, <code>Address</code>. If you want zero risk, store integers as <code>[u8; 8]</code> and reach for <code>u64::from_le_bytes(...)</code> at the read site. Align-1 structs never pad.</p>
</li>
<li><p><strong>Otherwise, order fields by descending alignment</strong> (biggest align first) to kill internal padding.</p>
</li>
<li><p><strong>Add an explicit</strong> <code>_padding: [u8; N]</code> to round the total up to the max alignment, killing trailing padding. Now the padding is a real IDL field and the client sends it.</p>
</li>
<li><p><strong>Verify</strong> <code>size_of::&lt;T&gt;() == Σ field sizes</code><strong>.</strong> A <code>const _: () = assert!(...)</code> on that equality turns this whole class of bug into a build error.</p>
</li>
</ol>
<h2>Test yourself</h2>
<p>Predict <code>size_of</code>, <code>Σ field sizes</code>, and the padding for each. Answers below.</p>
<ol>
<li><p><code>{ u8, u8, u16 }</code></p>
</li>
<li><p><code>{ u16, u8, u8 }</code></p>
</li>
<li><p><code>{ u32, u8 }</code></p>
</li>
<li><p><code>{ Address, u32 }</code></p>
</li>
<li><p><code>{ u64, u32, u32 }</code></p>
</li>
<li><p><code>{ u8, u128 }</code> Answers:</p>
</li>
<li><p>size 4, sum 4, <strong>0</strong> (<code>u16</code> at offset 2 is already aligned; total 4 is a multiple of 2).</p>
</li>
<li><p>size 4, sum 4, <strong>0</strong> (<code>u16</code> at 0, <code>u8</code> at 2, <code>u8</code> at 3; total 4).</p>
</li>
<li><p>size 8, sum 5, <strong>3 trailing</strong> (<code>u32</code> at 0, <code>u8</code> at 4 gives 5, round up to 8).</p>
</li>
<li><p>size 36, sum 36, <strong>0</strong> (<code>Address</code> align 1 at 0..32, <code>u32</code> needs align 4, and 32 % 4 == 0 so no gap; total 36 is a multiple of 4).</p>
</li>
<li><p>size 16, sum 16, <strong>0</strong> (<code>u64</code> at 0, <code>u32</code> at 8, <code>u32</code> at 12 gives 16, a multiple of 8).</p>
</li>
<li><p>size 32, sum 17, <strong>15</strong> (<code>u8</code> at 0, <code>u128</code> needs align 16 so it lands at 16, giving 15 bytes of internal padding; total 32).</p>
</li>
</ol>
<h2>Takeaway</h2>
<p>The bug was never in the data. It was in the seven bytes the compiler adds and the IDL does not describe. A zero-copy read wants the full <code>#[repr(C)]</code> layout; a borsh client sends packed fields; they agree only when <code>size_of::&lt;T&gt;() == Σ field sizes</code>. Run that layout loop in your head when you write the struct, or assert the equality so the compiler runs it for you. Either way it becomes a build error instead of a simulation log, which is where I wanted it.</p>
<h2>Why this post exists</h2>
<p>This came out of building pinoc, my IDL and client generator for pinocchio programs. I hit the padding mismatch in my own work: the client kept getting <code>custom program error: 0x0</code> even though the arguments were correct, and it took a while of banging my head against it before the size mismatch clicked. Once it did, I figured the write-up was worth reconciling into something the community could use, since the next person to add a <code>u64</code> to a <code>#[repr(C)]</code> args struct is going to hit exactly this.</p>
<p>The IDL and client generation that surfaced all of this ships with pinoc v0.2.0. If you want to try it or read the layout guards for yourself, the source is here: <a href="https://github.com/A91y/pinoc">github.com/A91y/pinoc</a>.</p>
<p>If you have questions or want to poke at it, I am on X at <a href="https://x.com/AyushAgr91">@AyushAgr91</a>.</p>
<h2>Further reading</h2>
<p>For the authoritative rules behind everything above, the Rust Reference on type layout is the source of truth: <a href="https://doc.rust-lang.org/reference/type-layout.html">https://doc.rust-lang.org/reference/type-layout.html</a>.</p>
<p>This is the first post in a series on low-level Solana and pinocchio work. More is coming :)</p>
]]></content:encoded></item><item><title><![CDATA[Unleashing the Power of ChatGPT: Revolutionizing Conversational AI]]></title><description><![CDATA[Introduction
In recent years, Artificial Intelligence (AI) has made significant strides in enhancing our everyday lives. From virtual assistants to personalized recommendations, AI has become an integral part of our digital ecosystem. Among the notab...]]></description><link>https://blog.ayushagr.me/unleashing-the-power-of-chatgpt</link><guid isPermaLink="true">https://blog.ayushagr.me/unleashing-the-power-of-chatgpt</guid><category><![CDATA[chatgpt]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[GPT 3]]></category><category><![CDATA[openai]]></category><dc:creator><![CDATA[Ayush Agrawal]]></dc:creator><pubDate>Tue, 16 May 2023 16:05:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/rv2ooDQuNuI/upload/556f5040e95d7d2266e563f22a136efd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>In recent years, Artificial Intelligence (AI) has made significant strides in enhancing our everyday lives. From virtual assistants to personalized recommendations, AI has become an integral part of our digital ecosystem. Among the notable advancements in AI, ChatGPT stands tall as a powerful conversational agent, transforming the way we interact with machines. In this blog, we'll delve into the world of ChatGPT, exploring its capabilities, applications, and the impact it has on various domains.</p>
<h1 id="heading-understanding-chatgpt">Understanding ChatGPT</h1>
<p>ChatGPT is an advanced language model developed by OpenAI. Built upon the GPT-3.5 architecture, it leverages deep learning techniques to generate human-like responses in real-time conversations. Trained on vast amounts of data, including books, articles, and web pages, ChatGPT possesses a remarkable ability to understand context, contextually respond, and even exhibit a sense of creativity.</p>
<h2 id="heading-capabilities-and-features">Capabilities and Features</h2>
<ol>
<li><p>Natural Language Understanding: ChatGPT excels in understanding and processing human language. It can comprehend complex queries, interpret user intent, and extract key information from the conversation to provide meaningful responses.</p>
</li>
<li><p>Contextual Understanding: One of the most impressive aspects of ChatGPT is its contextual understanding. It can maintain context throughout a conversation, remembering and referring back to previous interactions. This feature enables more coherent and relevant responses, making the conversation feel more human-like.</p>
</li>
<li><p>Flexibility and Adaptability: ChatGPT can converse on a wide range of topics, displaying its versatility across various domains. Whether it's discussing technology, history, or current events, ChatGPT can provide valuable insights and engage users in a meaningful dialogue.</p>
</li>
<li><p>Creative Expression: Beyond merely providing informative responses, ChatGPT can exhibit a degree of creativity. It can generate imaginative text, write stories, and even compose poetry. This unique aspect makes interactions with ChatGPT more engaging and enjoyable.</p>
</li>
</ol>
<h1 id="heading-applications-of-chatgpt">Applications of ChatGPT</h1>
<ol>
<li><p>Customer Support: ChatGPT has the potential to revolutionize customer support by providing instant assistance and resolving common queries. Its ability to understand natural language and context enable it to address customer concerns efficiently, improving overall satisfaction.</p>
</li>
<li><p>Personalized Recommendations: With its vast knowledge base, ChatGPT can offer personalized recommendations for products, services, or content based on user preferences. This enhances the user experience and helps businesses increase customer engagement.</p>
</li>
<li><p>Education and Learning: ChatGPT can act as an interactive tutor, providing explanations, answering questions, and guiding learners through various subjects. Its ability to adapt and respond in real-time makes it a valuable resource for students and educators alike.</p>
</li>
<li><p>Content Generation: Writers, bloggers, and content creators can leverage ChatGPT to overcome writer's block or generate new ideas. By interacting with ChatGPT, they can receive suggestions, refine drafts, and explore creative avenues.</p>
</li>
</ol>
<h1 id="heading-ethical-considerations">Ethical Considerations</h1>
<p>While ChatGPT showcases remarkable capabilities, its deployment also raises ethical concerns. OpenAI acknowledges the potential misuse of such powerful technology and emphasizes responsible AI usage. Safeguards must be in place to prevent malicious intent, misinformation, and the dissemination of biased or harmful content. Continual improvements in AI ethics, transparency, and accountability are crucial to ensure the responsible use of ChatGPT and similar systems.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>ChatGPT, with its impressive language understanding and generation abilities, represents a major milestone in the field of conversational AI. Its applications span various domains, revolutionizing customer support, personalized recommendations, education, and content creation. However, as we embrace this technology, we must also prioritize ethical considerations to harness its potential responsibly. ChatGPT's advancements open the doors to a new era of human-machine interaction, blurring the lines between artificial and human intelligence, and empowering us to explore uncharted realms of possibility.</p>
<p><em>Fun fact :</em> <code>This article is written in collaboration with ChatGPT</code></p>
]]></content:encoded></item><item><title><![CDATA[Reality of Marketing in Real Life]]></title><description><![CDATA[Hello there, Reader of this article! I have a question for you, be truthful: "Do you really need most the products you own ? Look around yourself and think."
Now, ask from yourself why you bought the most unusable products you have. 
Rest your health...]]></description><link>https://blog.ayushagr.me/reality-of-marketing-in-real-life</link><guid isPermaLink="true">https://blog.ayushagr.me/reality-of-marketing-in-real-life</guid><category><![CDATA[marketing]]></category><category><![CDATA[Business and Finance ]]></category><category><![CDATA[General Advice]]></category><category><![CDATA[lifestyle]]></category><dc:creator><![CDATA[Ayush Agrawal]]></dc:creator><pubDate>Wed, 24 Nov 2021 05:37:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1637730570246/GZARj50tN.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello there, Reader of this article! I have a question for you, be truthful: "Do you really need most the products you own ? Look around yourself and think."</p>
<p>Now, ask from yourself why you bought the most unusable products you have. </p>
<p>Rest your healthy brain and let me answer. The most favourable answer that you may not is "<em>Marketing</em>", either you had watched the product review on social media, youtube, television or your friends and relatives might own that.</p>
<blockquote>
<p>Marketers often play some unethical practices to sell their product.</p>
</blockquote>
<p>Most of the product you have are useless. Here's a guide how to make right decision before buying a products and how companies try to alter your buying decisions.</p>
<p>Let's talk about what an average consumer expect and really get from companies. </p>
<h1 id="heading-consumers-expectation-and-reality">Consumer's Expectation and Reality</h1>
<h3 id="heading-expectation">Expectation</h3>
<ol>
<li>Companies will identify what problem customers are facing in their day-to-day life as well as in business tasks.</li>
<li>Finally come up with a product that solves all of them at once.</li>
</ol>
<blockquote>
<p>Most of the companies don't work like that, what they really do is...</p>
</blockquote>
<h3 id="heading-reality">Reality</h3>
<ol>
<li>Companies create a new problem that never actually existed.</li>
<li>Make that problem really harder to get solved.</li>
<li>Come up with multiple products which adds up and pretend to solve each of your problems and satisfies (fools) the customer.</li>
<li>Now-a-days companies also divide same product into multiple parts so that you can generate more income for them.</li>
</ol>
<h2 id="heading-example-of-evil-marketing">Example of evil marketing</h2>
<p>The biggest example of this is world largest tech company <code>Apple</code>. 
An ideal smartphone consumer buying a phone also need a charger. Now, Apple divided this one product into two parts -</p>
<ol>
<li>A phone</li>
<li>Charger</li>
</ol>
<p>They tend to save environment by removing charger from the box but this problem can never be solved in this way. In order to complete a smartphone, customer will buy a charger separately, that means separate packaging and delivery is required making the environmental problems worse.
Today, not only Apple but several other companies too are performing same tactics to fool you. </p>
<h1 id="heading-how-to-protect-ourselves-from-these-tactics">How to protect ourselves from these tactics ?</h1>
<p>In order to cope up with these issue, you have to ask few questions from youself and complete a checklist.</p>
<ol>
<li>Do I have enough money to buy it or I have to get loan ?</li>
<li>What value will this product  add into my life ? </li>
<li>Do I really need it or I am buying it just for flexing ?</li>
</ol>
<p>When you complete this checklist, you'll get a better decision making for the products. Now, you can differentiate between what you need and what they wanted to sell you forcefully.</p>
<blockquote>
<p><em>Now that said, dear reader, whoever you are. Thank you for reading, and I hope you have a wonderful day.</em></p>
</blockquote>
<p>Cheer if you enjoyed, Share to distribute knowledge, Comment to share your valuable views. <em><code>'Improvement suggestions are welcomed'</code> </em></p>
]]></content:encoded></item></channel></rss>